简体   繁体   English

当一个未来任务预期结果时继续

[英]Continue when one future task has expected result

I have 3 FutureTask<T> Objects. 我有3个FutureTask<T>对象。 I want that they are processed asynchronously. 我希望它们是异步处理的。 However, as soon as one of the FutureTasks' get() methods doesn't return null I want to continue ie my method (wrapper) returns and doesn't wait until the other two FutureTasks are processed. 但是,只要其中一个FutureTasks的get()方法没有返回null我想继续,即我的方法(包装器)返回并且不等到处理其他两个FutureTasks。 I thought about something like: 我想到了类似的东西:

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) { }
}

I'm not sure how to capture the exceptions (thrown by the get()) in a proper way because I assume they will be thrown since I just return without waiting for the other two tasks to be completed. 我不确定如何以正确的方式捕获异常(由get()抛出),因为我假设它们将被抛出,因为我只是返回而不等待其他两个任务完成。 Moreover I've doubts that the code will work like intended. 此外,我怀疑代码是否会像预期的那样工作。 I feel that I'm close to the solution but missing something. 我觉得我接近解决方案但却遗漏了一些东西。

May I suggest to check for FutureTask::isDone? 我可以建议检查FutureTask :: isDone吗?

Would be something like this then: 那会是这样的:

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

EDIT: You could cancel the other tasks as soon as you have one result at hand. 编辑:您可以在手头有一个结果后立即取消其他任务。

Using FutureTask::get is not what you look for as it would most likely always return the result of normal.get() because the documentation already states that: 使用FutureTask :: get不是你想要的,因为它很可能总是返回normal.get()的结果,因为文档已经说明:

Waits if necessary for the computation to complete, and then retrieves its result. 如果需要等待计算完成,然后检索其结果。

To clarify the above: If you use FutureTask::get the first FutureTask you call get on will most likely block and wait until a result is available to return. 为了澄清上述内容:如果你使用FutureTask :: get第一个FutureTask你调用get on很可能会阻塞并等待结果可用返回。

EDIT2: EDIT2:

Wrap that loop into a new Runnable, executed by the ExecutorService, passing the first result available to another method or implement a Callback and there's no more busy waiting. 将该循环包装到一个新的Runnable中,由ExecutorService执行,将第一个结果传递给另一个方法或实现一个Callback,并且不再忙于等待。

I had an idea to design it using BlockingQueue. 我有一个想法,使用BlockingQueue设计它。 You extend your tasks with done method submitting results into BlockinQueue and, once client received first result, it cancels other tasks. 您可以使用done方法将结果扩展到BlockinQueue,并在客户端收到第一个结果后取消其他任务。 On the other hand, experts suggest using ExecutorCompletionService instead. 另一方面, 专家建议使用ExecutorCompletionService It seems to serialize results imself and has all appropriate examples . 它似乎自己序列化结果,并有所有适当的例子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM