FutureTask get vs run,任务永远不会完成

时间:2021-03-11 19:08:09

标签: java callable futuretask

我正在学习 Callables 并决定制作一个非常简单的程序。问题是当我调用 getFutureTask(); 时线程被阻塞了; Thread.State: TIMED_WAITING(在对象监视器上)

当我在 futureTask.get() 之前编写 futureTask.run() 时,你能告诉我为什么会这样吗? 我明白 get() 方法等待并返回结果。但无法理解 run() 方法的作用。 我非常感谢您的回答!

   public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
       FutureTask futureTask = getFutureTask(1);
        System.out.println(futureTask.get());

    }


  public static FutureTask<Integer> getFutureTask(Integer i) {
        return new FutureTask<Integer>(() -> i*45);

    }

3 个答案:

答案 0 :(得分:3)

来自 FutureTask 的 API:

<块引用>

get() - 必要时等待计算完成,然后 检索其结果。

run() - 将此 Future 设置为其计算结果,除非它 已取消。

因此,run() 将实际运行您的 FutureTask 并最终得出计算结果。 get() 另一方面给你结果,如果计算完成。 但是它不会开始计算,也不会调用 run() 本身。

另见@Zabuzard 的评论:

<块引用>

run 是实际开始执行任务的方法。这是 应该在不同的线程中调用,例如由 执行者服务。 get 不会触发执行,它只是等到 任务完成,这发生在 run() 的末尾。 FutureTask 不是 真的应该由用户直接使用。相反,你应该 查看 ExecutorService 和 CompletableFuture 以获得漂亮的界面 产生异步任务。

答案 1 :(得分:3)

run vs get

run 是实际开始执行任务的方法。它应该在不同的线程中调用,例如由 ExecutorService 调用。

get不触发执行,它只是等到任务完成,即直到 run 完成。这显然意味着您以某种方式在不同线程之前或从不同线程调用 run


ExecutorServiceCompletableFuture

FutureTask 实际上不应该由用户直接使用。它更多是在幕后使用的类类型,以实现一个很好的异步 API。更具体地说,它是 Future 的基本实现,例如当您使用它生成任务时由 ExecutorService 返回。

相反,您应该查看 ExecutorService

ExecutorService service = Executors.newCachedThreadPool();
...
Future<Integer> task = service.submit(() -> i * 45);
...
Integer result = task.get();

CompletableFuture

CompletableFuture<Integer> task = CompletableFuture.supplyAsync​(() -> i * 45);
...
Integer result = task.get();

一个易于使用的界面来生成异步任务。

CompletableFuture 的优点是您还可以设置一个操作管道,一旦前一个操作完成,这些操作将全部异步执行。例如:

CompletableFuture<Void> task = CompletableFuture.supplyAsync(Foo::readSomeFile)
    .thenApplyAsync(Foo::validateData)
    .thenApplyAsync(Foo::compressData)
    .thenAcceptAsync(Foo::uploadData);

答案 2 :(得分:2)

你的函数 () -> i*45 只是一个可调用的。除非您真正开始执行,否则它不会真正执行。 而这正是 run() 的用途。

因此,除非您没有明确启动线程,否则不会调用 FutureTask 的任何内容。 而 get() 旨在等待线程完成。 因此,通常情况下,您正在启动一项任务(使用 run()),执行其他一些操作,然后使用 get() 获得结果,或者如果任务花费的时间比预期的要长,则在那里等待。

你可以检查一下,例如通过运行一些 System.out:

 public static FutureTask<Integer> getFutureTask(Integer i) {
    return new FutureTask<Integer>(() -> {
        System.out.println("Task started");
        return i * 45;
    });
}

你什么都看不到