问题引出:
使用线程池,怎么阻塞等待所有线程执行完成后,才能继续走下面的逻辑?
使用awaitTermination只能阻塞等待定时时间,超过该时间后,主线程不再阻塞等待,而线程池中的线程仍会继续运行。
executorService.shutdown();
boolean taskCompleted = executorService.awaitTermination(6, TimeUnit.HOURS);
if (!taskCompleted) {
executorService.shutdownNow();
throw new IllegalStateException("任务超时,未完成!");
}
方法一:
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
...
}
official documentation that Long.MAX_VALUE, TimeUnit.NANOSECONDS
is equivalent to not having a timeout :
java.util.concurrent
package documentation under the Timing
section: To wait "forever", you can use a value of Long.MAX_VALUE
方法二:
CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
taskExecutor.execute(new MyTask());
}
try {
latch.await();
} catch (InterruptedException E) {
// handle
}
and within your task (enclose in try / finally)
latch.countDown();
该方法由一个弊端是:需要提前知道totalNumberOfTasks
方法三:
You can use Lists of Futures, as well:
List<Future> futures = new ArrayList<Future>();
// now add to it:
futures.add(executorInstance.submit(new Callable<Void>() {
public Void call() throws IOException {
// do something
return null;
}
}));
then when you want to join on all of them, its essentially the equivalent of joining on each, (with the added benefit that it re-raises exceptions from child threads to the main):
for(Future f: this.futures) { f.get(); }
方法四:
you can do it with CompletableFuture:
ExecutorService es = Executors.newFixedThreadPool(4);
List<Runnable> tasks = getTasks();
CompletableFuture<?>[] futures = tasks.stream()
.map(task -> CompletableFuture.runAsync(task, es))
.toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();
es.shutdown();
转载自:How to wait for all threads to finish, using ExecutorService?