【问题标题】:How can you tell when a Future object is done with its task?如何判断 Future 对象何时完成其任务?
【发布时间】:2019-10-10 10:05:24
【问题描述】:

我正在使用 Java 8。我想知道如何判断 Future 对象何时完成其任务。我尝试通过编写以下内容来理解它

    Callable<Long> c = new Callable<Long>() {

        @Override
        public Long call() throws Exception {
            return new Long(factorial(1));
        }

    };

    ExecutorService s = Executors.newFixedThreadPool(2);
    Future<Long> f = s.submit(c);

    while (!f.isDone())
    {
        System.out.println("waiting..." + f.get().toString());
    }   // while
    System.out.println(f.get().toString());

但 while 循环永远不会返回(f.isDone() 始终为 false),即使我知道有一个计算结果。

【问题讨论】:

  • 为什么要同步等待异步任务完成?这和在你当前的同步码流中做任务一样好。
  • Future.get() 是一种阻塞方法。这是根本。
  • 如果factorial 返回long(或可以转换为long 的原语),则无需调用new Long(...),Java 将为您自动装箱。跨度>

标签: java multithreading future callable


【解决方案1】:

它可以工作,但是您永远不会关闭您创建的池。您可以在 ExecutorService 文档中了解此内容。在最后添加这个来关闭你的池:

s.shutdown();
try {
    if(!s.awaitTermination(3, TimeUnit.SECONDS)) {
          s.shutdownNow();
    }
} catch (InterruptedException e) {
    s.shutdownNow();
}

进一步说明

Future::get 是一个阻塞操作。在某些情况下,您的循环可能永远不会被调用,因为未来维护的任务可能在评估循环条件之前完成。但在大多数情况下,在第一次循环迭代中,您将调用Future::get,这是阻塞操作。然后你得到结果,循环条件再次被评估为假,因为未来已经完成。总而言之 - 您的循环将被调用 0 或 1 次。之后,您必须按照我之前写的那样关闭池。

【讨论】:

  • 我想,这不是他正在寻找的答案。他很想知道为什么循环不起作用。
【解决方案2】:

没有。它很快就会完成。在您的情况下,您将打印“waiting... 1”和 1。

如果你调试一下,就会清楚很多。

至于线程保持运行,那是因为 Executors。

池中的线程将一直存在,直到它被显式关闭。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    相关资源
    最近更新 更多