IT TIP

Executor를 종료하지 않고 ThreadPoolExecutor의 모든 작업이 완료 될 때까지 기다리는 방법은 무엇입니까?

itqueen 2020. 12. 8. 20:32
반응형

Executor를 종료하지 않고 ThreadPoolExecutor의 모든 작업이 완료 될 때까지 기다리는 방법은 무엇입니까?


내가 사용할 수 없습니다 shutdown()awaitTermination()것이 가능하기 때문에 대기 중에 새로운 작업은 ThreadPoolExecutor에 추가됩니다.

따라서 ThreadPoolExecutor가 대기열을 비우고 해당 시점 이전에 새 작업이 추가되는 것을 막지 않고 모든 작업을 완료 할 때까지 기다리는 방법을 찾고 있습니다.

차이가 있다면 Android 용입니다.

감사

업데이트 : 몇 주 후에 이것을 다시 방문한 후 수정 된 CountDownLatch가이 경우에 더 잘 작동한다는 것을 발견했습니다. 내가 요청한 내용에 더 많이 적용되므로 답을 표시해 두겠습니다.


특정 작업이 완료되는시기 또는 특정 작업 일괄 처리를 알고 싶다면 ExecutorService.submit(Runnable). 이 메서드를 호출하면에 Future배치 될 수 있는 객체가 반환되며,이 객체는 Collection주 스레드가 Future.get()객체 에 대해 호출 반복 합니다. 이로 인해 주 스레드가 ExecutorService모든 Runnable작업을 처리 할 때까지 실행을 중지 합니다.

Collection<Future<?>> futures = new LinkedList<Future<?>>();
futures.add(executorService.submit(myRunnable));
for (Future<?> future:futures) {
    future.get();
}

My Scenario는 웹 사이트에서 일부 정보를 가져와 처리하는 웹 크롤러입니다. ThreadPoolExecutor는 시간에 많은 페이지를로드 할 수 있으므로 프로세스 속도를 높이는 데 사용됩니다. 따라서 크롤러가 각 페이지의 하이퍼 링크를 따르기 때문에 기존 작업에 새 작업이 생성됩니다. 문제는 동일합니다. 메인 스레드는 모든 작업이 언제 완료되었는지 알지 못하며 결과 처리를 시작할 수 있습니다. 이것을 결정하는 간단한 방법을 사용합니다. 매우 우아하지는 않지만 내 경우에는 작동합니다.

while (executor.getTaskCount()!=executor.getCompletedTaskCount()){
    System.err.println("count="+executor.getTaskCount()+","+executor.getCompletedTaskCount());
    Thread.sleep(5000);
}
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);

작업 배치를 관리하기 위해 CompletionService찾고있을 수 있습니다. 이 답변 도 참조하십시오 .


(이것은 Thilo의 이전 삭제 된 답변을 내 자신의 조정으로 재현하려는 시도입니다.)

암시 적 무한 조건이 있기 때문에 질문을 명확히해야한다고 생각합니다. 언젠가는 실행기를 종료하기로 결정해야하며 그 시점에서 더 이상 작업을 수락하지 않습니다. 귀하의 질문은 자신의 애플리케이션 코드에서만 알 수있는 추가 작업이 제출되지 않을 것이라는 것을 때까지 기다리기를 원한다는 것을 암시하는 것 같습니다 .

다음 답변을 통해 (어떤 이유로 든) 새 TPE로 원활하게 전환하고 현재 제출 된 모든 작업을 완료하고 새 TPE에 대한 새 작업을 거부하지 않을 수 있습니다. 귀하의 질문에 답할 수 있습니다. @Thilo의 수도 있습니다.

다음과 같이 사용중인 가시적 인 TPE를 어딘가에 정의했다고 가정합니다.

AtomicReference<ThreadPoolExecutor> publiclyAvailableTPE = ...;

그런 다음 TPE 스왑 루틴을 이와 같이 작성할 수 있습니다. 동기화 된 메서드를 사용하여 작성할 수도 있지만 이것이 더 간단하다고 생각합니다.

void rotateTPE()
{
   ThreadPoolExecutor newTPE = createNewTPE();
   // atomic swap with publicly-visible TPE
   ThreadPoolExecutor oldTPE = publiclyAvailableTPE.getAndSet(newTPE);
   oldTPE.shutdown();

   // and if you want this method to block awaiting completion of old tasks in  
   // the previously visible TPE
   oldTPE.awaitTermination();
} 

또는 스레드 풀을 죽이고 싶지 않은 농담이 없다면 제출자 측이 어느 시점에서 거부 된 작업에 대처해야 null하며 새 TPE에 사용할 수 있습니다 .

void killTPE()
{
   ThreadPoolExecutor oldTPE = publiclyAvailableTPE.getAndSet(null);
   oldTPE.shutdown();

   // and if you want this method to block awaiting completion of old tasks in  
   // the previously visible TPE
   oldTPE.awaitTermination();
} 

업스트림 문제를 일으킬 수있는 호출자는 null.

새로운 실행을 모두 거부하는 더미 TPE로 교체 할 수도 있지만, shutdown()이는 TPE 를 호출 할 때 발생하는 것과 동일합니다 .


을 사용하지 않으려면 shutdown다음 접근 방식을 따르십시오.

  1. Future제출 부터 모든 작업을 반복 하고 제안 된대로 객체 에 대한 ExecutorService호출 get()차단하여 상태를 확인합니다.FutureTim Bender

  2. 다음 중 하나 사용

    1. 사용 invokeAll을을ExecutorService
    2. CountDownLatch 사용
    3. Using ForkJoinPool or newWorkStealingPool of Executors(since java 8)

invokeAll() on executor service also achieves the same purpose of CountDownLatch

Related SE question:

How to wait for a number of threads to complete?


You could call the waitTillDone() on Runner class:

Runner runner = Runner.runner(10);

runner.runIn(2, SECONDS, runnable);
runner.run(runnable); // each of this runnables could submit more tasks

runner.waitTillDone(); // blocks until all tasks are finished (or failed)

// and now reuse it

runner.runIn(500, MILLISECONDS, callable);

runner.waitTillDone();
runner.shutdown();

To use it add this gradle/maven dependency to your project: 'com.github.matejtymes:javafixes:1.0'

For more details look here: https://github.com/MatejTymes/JavaFixes or here: http://matejtymes.blogspot.com/2016/04/executor-that-notifies-you-when-task.html


Try using queue size and active tasks count as shown below

 while (executor.getThreadPoolExecutor().getActiveCount() != 0 || !executor.getThreadPoolExecutor().getQueue().isEmpty()){
                     try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }

참고URL : https://stackoverflow.com/questions/3929361/how-to-wait-for-all-tasks-in-an-threadpoolexecutor-to-finish-without-shutting-do

반응형