[英]How to wait until all submitted tasks in ExecutorService are completed without shutdown?
[英]How to check if all tasks running on ExecutorService are completed
我有用于同步推送/弹出元素的 ConcurrentLinkedDeque,并且我有一些异步任务,它们从堆栈中获取一个元素,如果该元素有邻居,它会将其推送到堆栈。
示例代码:
private ConcurrentLinkedDeque<Item> stack = new ConcurrentLinkedDeque<>();
private ExecutorService exec = Executors.newFixedThreadPool(5);
while ((item = stack.pollFirst()) != null) {
if (item == null) {
} else {
Runnable worker = new Solider(this, item);
exec.execute(worker);
}
}
class Solider{
public void run(){
if(item.hasNeighbors){
for(Item item:item.neighbors){
stack.push(item)
}
}
}
}
我想在 while 循环中有额外的语句来回答这个问题 - “Executor 中的任何任务都在工作吗?”
如果您使用ExecutorService.execute(Runnable)
则没有一种干净的方法来检查是否所有 Runnable 都已完成。 除非您在 Runnable 本身中构建了一个机制来这样做(在我看来这很草率)。
反而:
使用ExecutorService.submit(Runnable)
。 此方法将返回一个Future<?>
,它是Runnable
结果的句柄。 使用 Futures 提供了一种干净的方法来检查结果。
你所要做的就是维护一个你提交的 Futures 列表,然后你可以遍历整个 Futures 列表,或者:
A)等待所有期货以阻塞方式完成或
B) 检查所有期货是否以非阻塞方式完成。
这是一个代码示例:
List<Future<?>> futures = new ArrayList<Future<?>>();
ExecutorService exec = Executors.newFixedThreadPool(5);
// Instead of using exec.execute() use exec.submit()
// because it returns a monitorable future
while((item = stack.pollFirst()) != null){
Runnable worker = new Solider(this, item);
Future<?> f = exec.submit(worker);
futures.add(f);
}
// A) Await all runnables to be done (blocking)
for(Future<?> future : futures)
future.get(); // get will block until the future is done
// B) Check if all runnables are done (non-blocking)
boolean allDone = true;
for(Future<?> future : futures){
allDone &= future.isDone(); // check if future is done
}
更新:使用 Java 8+ CompletableFutures,您可以使用其新的回调函数来管理它。 首先,您需要创建您需要的所有 CompletableFutures,它们也将开始运行,例如:
我们需要累积在 Array 中生成的所有期货,以便稍后将它们传递给 CompletableFuture.allOf(CompletableFutures...)
因此,假设您有一个要异步计算其生日前天数的人员列表:
首先,我们创建所有需要的期货并将它们收集在一个数组中:
CompletableFuture<?>[] completables = people.stream()
.map(p -> createCompletableFuture(p))
.toArray(CompletableFuture<?>[]::new);
private CompletableFuture createCompletableFuture(Person p) {
return CompletableFuture.runAsync(daysUntillBirthday(p));
}
然后将这些可完成项传递给新的 CompletableFuture:
CompletableFuture c = CompletableFuture.allOf(completables)
您现在可以检查是否仍有期货在运行:
c.isDone()
这可能不是最干净的解决方案,但您可以使用ThreadPoolExecutor.getActiveCount()
检查有多少线程正在积极执行任务。
在 while 循环中使用一个简单的条件来实现这一点,以检查活动线程数是否为零,这是一个可口的解决方案。
这是一个代码示例:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
for (int x = 0; x < 4; x++) {
Runnable worker = new Solider(this,item);
executor.execute(worker);
}
// Now check for active threads.
while(executor.getActiveCount()!=0)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
while 块直接回答您的问题。 IE - 如果 while 块处于活动状态,则正在执行任务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.