Java ExecutorsService 提交一个 FutureTask 获取 Future returns null

Java ExecutorsService submit a FutureTask get on Future returns null

我有这个片段。

    final ExecutorService executor = Executors.newFixedThreadPool(3);
    final Runnable runnable = ()->{System.out.println("Inside runnable run method");};
    final Callable<String>callable = ()->{System.out.println("Inside callable call method");return "callable";};
    final FutureTask<String> futureTask = new FutureTask<>(()->{System.out.println("CallableInFutureTask");},"JOHN");
    final FutureTask f1 = (FutureTask)executor.submit(callable);
    final FutureTask f2 = (FutureTask)executor.submit(futureTask);
    final FutureTask f3 = (FutureTask)executor.submit(runnable);
    System.out.println("f1 = " + f1+" "+f1.isDone()+" "+f1.get());
    System.out.println("FutureTask Reference Object: "+futureTask.isDone()+" "+futureTask.get());
    System.out.println("f2 = "+f2.isDone()+" "+f2.get());
    System.out.println("f3 = " + f3+" "+f3.isDone()+" "+f3.get());        
    executor.shutdown();

f1 和 f3 Future 变量 returning 其 get 方法的正确值,但 FutureTask 通过它传递给 Executors f2 returning null 这是为什么?即使是 futureTask 引用 returning 了 get 方法的正确值 "JOHN" 但这是为什么呢?也许是因为我正在通过 FutureTask?没看懂。

我只是认为 f2 和 futureTask 引用 return 具有相同的值。对不起,如果这个问题很简单,非常感谢。

return 是正确的。 f1 有一个 return,但 f2 和 f3 没有。 null 在这里代表 void

当您将 FutureTask 提交给 ExecutorService 时,它会被视为 Runnable,因此您从 submit 方法获得的 Future 将具有 null 的值,因为 Runnable 个实例没有 return 任何结果。

由于 FutureTask 实现了 Runnable 接口,ExecutorService 的这个方法被称为 submit(Runnable task) 所以 Runnable 你包装在 FutureTask 构造函数实际上已提交给 ExecutorService ,因此您在调用 f2.get().

时得到 null

但是当您在 FutureTask 引用上调用 get() 时,一旦 Runnable 具有 ,您将取回作为第二个参数提供的值完成了它的执行 (当您在 ExecutorService 之前提交任务时)。

您也可以通过 不提交 ExecutorService 中的 futureTask 来验证这一点,然后如果您尝试调用 futureTask 变量 get 调用将无限期阻塞,因为 Runnable 尚未执行。

 // Returning "JOHN" when the supplied Runnable is completed execution.
 System.out.println("FutureTask Reference Object: "+futureTask.isDone()+" "+futureTask.get());

这是根据 docs:

Creates a FutureTask that will, upon running, execute the given Runnable, and arrange that get will return the given result on successful completion.