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다음 접근 방식을 따르십시오.
Future제출 부터 모든 작업을 반복 하고 제안 된대로 객체 에 대한ExecutorService호출get()을 차단하여 상태를 확인합니다.FutureTim Bender다음 중 하나 사용
- 사용 invokeAll을을 에
ExecutorService - CountDownLatch 사용
- Using ForkJoinPool or newWorkStealingPool of
Executors(since java 8)
- 사용 invokeAll을을 에
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) {
}
}
'IT TIP' 카테고리의 다른 글
| MySQL 트리거에서 PHP 스크립트 호출 (0) | 2020.12.08 |
|---|---|
| 반복기의 기본값은 무엇입니까? (0) | 2020.12.08 |
| char * envp []는 main () 휴대용에 대한 세 번째 인수입니다. (0) | 2020.12.08 |
| Laravel 5에서 예외 / 누락 된 페이지를 어떻게 잡나요? (0) | 2020.12.07 |
| 클래스의 함수 (메소드) 가져 오기 (0) | 2020.12.07 |