6

我有 3 个FutureTask<T>对象。我希望它们被异步处理。但是,一旦 FutureTasks 的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() 抛出),因为我假设它们会被抛出,因为我只是返回而不等待其他两个任务完成。此外,我怀疑代码是否会按预期工作。我觉得我接近解决方案但缺少一些东西。

4

2 回答 2

1

我可以建议检查一下 FutureTask::isDone 吗?

会是这样的:

while(true) {
    if (normal.isDone()) {
        return normal.get();
    }
    if (medium.isDone()) {
        return medium.get();
    }
    if (huge.isDone()) {
        return huge.get();
    }
}

编辑:只要手头有一个结果,您就可以取消其他任务。

使用FutureTask::get不是您要寻找的,因为它很可能总是返回 normal.get() 的结果,因为文档已经指出:

如有必要,等待计算完成,然后检索其结果。

为了澄清上述内容:如果您使用 FutureTask::get 您调用的第一个 FutureTask 很可能会阻塞并等待结果返回。

编辑2:

将该循环包装到一个新的 Runnable 中,由 ExecutorService 执行,将可用的第一个结果传递给另一个方法或实现一个回调,这样就不会再忙于等待了。

于 2015-07-20T13:04:15.293 回答
0

我有一个想法来使用 BlockingQueue 来设计它。您使用 done 方法将任务提交到 BlockinQueue 中,一旦客户端收到第一个结果,它就会取消其他任务。另一方面,专家建议改用 ExecutorCompletionService。它似乎对结果进行了序列化,并且具有所有适当的示例

于 2015-07-21T06:32:15.083 回答