知道执行者服务何时完成所有提交的任务的最佳方法是什么
what is the best way to know when all submitted tasks has been finished by Executor Service
这里有两个选项,只是有点混淆哪一个最好。
选项 1:
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();
选项 2:
ExecutorService es = Executors.newFixedThreadPool(4);
List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
futures.add(es.submit(task));
}
for(Future<?> future : futures) {
try {
future.get();
}catch(Exception e){
// do logging and nothing else
}
}
es.shutdown();
这里放future.get(); in try catch 是个好主意吧?
由于您通过这样做有效地将每个提交的 Future
保存在期货列表中:
List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
futures.add(es.submit(task));
}
您可以很容易地检查是否所有提交的作业都已完成执行,只需调用 Future#isDone
方法,该方法会根据任务是否完成来确定 return true 或 false。您可以在相关文档 here.
上查看更多信息
因此,考虑到上述情况,您可以很好地创建一个简单的辅助方法,它将迭代您的期货列表并检查它们的状态。例如:
private boolean areJobsDone() {
return futures.stream()
.allMatch(Future::isDone);
}
请注意,与 Future#get
方法相比,isDone
是非阻塞的(因为它不等待任务 return 它的结果),因为它有效地查询它的状态。
有了这个,您可以继续检查可运行对象的状态,在继续之前用调用辅助方法的循环阻塞流程。
希望对您有所帮助。
还有一种等待所有任务完成的方法。提交所有任务后,请致电
es.shutdown()
es.awaitTermination(Long.MAX_VALUE, TimeUnit.NANO_SECONDS)
shutdown [...] Initiates an orderly shutdown in which previously submitted tasks are executed.
awaitTermination [...] Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
关于超时:使用上述值,线程池将在大约 300 年后终止。
与 Aris_Kortex 提案类似,
List<CompletableFuture<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
futures.add(CompletableFuture.runAsync(task, es));
}
然后创建组合的 CompletableFuture:
CompletableFuture<Void> cf = CompletableFuture.allOf(futures.toArray(futires.size()));
那么你可以同步等待所有任务:
cf.get();
与超时同步:
cf.get(1, TimeUnit.SECOND);
异步:
cf.thenRun(()->{finalActions();});
这里有两个选项,只是有点混淆哪一个最好。
选项 1:
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();
选项 2:
ExecutorService es = Executors.newFixedThreadPool(4);
List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
futures.add(es.submit(task));
}
for(Future<?> future : futures) {
try {
future.get();
}catch(Exception e){
// do logging and nothing else
}
}
es.shutdown();
这里放future.get(); in try catch 是个好主意吧?
由于您通过这样做有效地将每个提交的 Future
保存在期货列表中:
List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
futures.add(es.submit(task));
}
您可以很容易地检查是否所有提交的作业都已完成执行,只需调用 Future#isDone
方法,该方法会根据任务是否完成来确定 return true 或 false。您可以在相关文档 here.
因此,考虑到上述情况,您可以很好地创建一个简单的辅助方法,它将迭代您的期货列表并检查它们的状态。例如:
private boolean areJobsDone() {
return futures.stream()
.allMatch(Future::isDone);
}
请注意,与 Future#get
方法相比,isDone
是非阻塞的(因为它不等待任务 return 它的结果),因为它有效地查询它的状态。
有了这个,您可以继续检查可运行对象的状态,在继续之前用调用辅助方法的循环阻塞流程。
希望对您有所帮助。
还有一种等待所有任务完成的方法。提交所有任务后,请致电
es.shutdown()
es.awaitTermination(Long.MAX_VALUE, TimeUnit.NANO_SECONDS)
shutdown [...] Initiates an orderly shutdown in which previously submitted tasks are executed.
awaitTermination [...] Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
关于超时:使用上述值,线程池将在大约 300 年后终止。
与 Aris_Kortex 提案类似,
List<CompletableFuture<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
futures.add(CompletableFuture.runAsync(task, es));
}
然后创建组合的 CompletableFuture:
CompletableFuture<Void> cf = CompletableFuture.allOf(futures.toArray(futires.size()));
那么你可以同步等待所有任务:
cf.get();
与超时同步:
cf.get(1, TimeUnit.SECOND);
异步:
cf.thenRun(()->{finalActions();});