我有3个FutureTask<T>
个对象。我希望它们是异步处理的。但是,只要其中一个FutureTasks&#39; get()
方法没有返回null
我想继续,即我的方法(包装器)返回并且不等到处理其他两个FutureTasks。
我想到了类似的东西:
private File wrapper(final File file) {
ExecutorService executors = Executors.newCachedThreadPool();
File returnFile;
FutureTask<File> normal= ...
FutureTask<File> medium=...
FutureTask<File> huge=...
executors.execute(normal);
executors.execute(medium);
executors.execute(huge);
try {
if((returnFile=normal.get()) != null ||
(returnFile=medium.get()) != null ||
(returnFile=huge.get()) != null)
return returnFile;
} catch(ExecutionException | InterruptedException e) { }
}
我不确定如何以正确的方式捕获异常(由get()抛出),因为我假设它们将被抛出,因为我只是返回而不等待其他两个任务完成。此外,我怀疑代码是否会像预期的那样工作。我觉得我接近解决方案但却遗漏了一些东西。
答案 0 :(得分:1)
我可以建议检查FutureTask :: isDone吗?
那会是这样的:
while(true) {
if (normal.isDone()) {
return normal.get();
}
if (medium.isDone()) {
return medium.get();
}
if (huge.isDone()) {
return huge.get();
}
}
编辑: 只要手头有一个结果,你就可以cancel完成其他任务。
使用FutureTask::get不是你想要的,因为它很可能总是返回normal.get()的结果,因为文档已经说明:
如果需要等待计算完成,然后检索 结果。
澄清以上内容: 如果你使用FutureTask :: get第一个FutureTask,你调用get on很可能会阻塞并等到结果可以返回。
EDIT2:
将该循环包装到一个新的Runnable中,由ExecutorService执行,将第一个结果传递给另一个方法或实现Callback,并且不再忙于等待。
答案 1 :(得分:0)
我有一个想法是使用BlockingQueue进行设计。您可以使用done方法将结果扩展到BlockinQueue,并在客户端收到第一个结果后取消其他任务。另一方面,experts suggest using ExecutorCompletionService代替。它似乎将结果序列化为自己和has all appropriate examples。