我得到了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中的任何任务都在工作吗?”
答案 0 :(得分:49)
如果您使用ExecutorService.execute(Runnable)
,则无法检查是否已完成所有Runnables。除非你在Runnable本身建立一个机制(在我看来这很草率)。
<强>相反:强>
使用ExecutorService.submit(Runnable)
。此方法将返回Future<?>
,它是runnable结果的句柄。使用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
}
答案 1 :(得分:0)
更新:使用Java 8+ CompletableFutures,您可以通过其新的回调函数进行管理。首先,您需要创建所需的所有CompletableFuture,它们也将开始运行,例如:
我们需要累计在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()