这是使用java.util.concurrent.FutureTask的好方法吗?

首先,我必须说我对API java.util.concurrent很陌生,所以也许我正在做的事情是完全错误的。

我想做什么?

我有一个Java应用程序,基本上运行2个单独的处理(称为myFirstProcessmySecondProcess),但这些处理必须同时运行。

所以,我试图这样做:

public void startMyApplication() {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
    FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
    executor.execute(futureOne);
    executor.execute(futureTwo);
    while (!(futureOne.isDone() && futureTwo.isDone())) {
        try {
            // I wait until both processes are finished.
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    logger.info("Processing finished");
    executor.shutdown();
    // Do some processing on results
    ...
}

myFirstProcessmySecondProcess 是实现 的类,它们的所有处理都是在 call() 方法中进行的。Callable<Object>

它运行良好,但我不确定这是正确的方法。做我想做的事是个好方法吗?如果没有,你能给我一些提示来增强我的代码(并且仍然尽可能保持简单)。


答案 1

你最好使用这种方法。get()

futureOne.get();
futureTwo.get();

两者都等待线程的通知,它完成了处理,这为您节省了您现在正在使用的忙等待计时器,这既没有效率也不优雅。

作为奖励,您有API,它允许您定义线程进入睡眠状态并等待响应以及继续运行的最长时间。get(long timeout, TimeUnit unit)

有关详细信息,请参阅 Java API


答案 2

上述用法是可以容忍的,但绝对不是惯用语。您实际上正在将额外的内容包裹在提交给 .您的被 .在内部,它会将您的 -as- 包装在新的中,并将其作为 .FutureTaskFutureTaskExecutorServiceFutureTaskRunnableExecutorServiceFutureTaskRunnableFutureTaskFuture<?>

相反,您应该将实例提交到完成服务。您将两个 s 放入 via ,然后转身并呼叫两次(每个提交一次)。这些调用将阻塞,直到一个,然后其他提交的任务完成。Callable<Object>Callablesubmit(Callable<V>)CompletionService#take()Callable

假设您已经掌握了一个,请围绕它构建一个新的执行器完成服务,并将您的任务放在那里。不要旋转和睡觉等待; 将阻塞,直到您的任一任务完成(完成运行或取消)或等待的线程中断。ExecutorCompletionService#take()take()


推荐