为啥 ExecutorService.submit(Runnable task) 返回 Future<?> 而不是 Future<Void>?

Posted

技术标签:

【中文标题】为啥 ExecutorService.submit(Runnable task) 返回 Future<?> 而不是 Future<Void>?【英文标题】:Why does ExecutorService.submit(Runnable task) return Future<?> rather than Future<Void>?为什么 ExecutorService.submit(Runnable task) 返回 Future<?> 而不是 Future<Void>? 【发布时间】:2017-10-13 22:23:09 【问题描述】:

ExecutorService有如下方法:

Future<?> submit(Runnable task)

但是既然Futureget方法总是会返回null,那么下面的签名不是更合适吗?

Future&lt;Void&gt; submit(Runnable task)

【问题讨论】:

【参考方案1】:

注意Runnablerun 方法返回void 原语而不是Void 类型。出于这个原因,Future 不能有 Void 类型,解决方案是使其成为通配符。请注意,Future 来自 java 1.5,而Runnable 来自 1.0。由于遗留代码原因,他们不会更改run 的返回类型以符合Future

【讨论】:

Future&lt;Void&gt; 的 get 方法将始终返回 null,这正是在这种情况下所要求的。 Future&lt;?&gt; 可以返回任何对象,而实际上在这种特殊情况下它总是返回 null,如 submit 方法的 javadoc 中所述。所以Future&lt;Void&gt; 在这里是正确的选择。类似地,如果run 会返回double,则Future&lt;Double&gt; 将比Future&lt;?&gt; 更合适。【参考方案2】:

jdk 1.8里面的submit方法实现用void,jdk1.6是Object。我的理解是用void更合适,所以jdk1.7/1.8改了。只支持接口不变它

 public Future<?> submit(Runnable task) 
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    

在 JDK 1.6 中

 public Future<?> submit(Runnable task) 
       if (task == null) throw new NullPointerException();
       RunnableFuture<Object> ftask = newTaskFor(task, null);
       execute(ftask);
        return ftask;
   

【讨论】:

是的,我知道他们不想在之后更改界面。但为什么它首先被定义为它的方式呢? Void 类型自 Java 1.1 起可用。所以我想这只是一个错误。【参考方案3】:

因为ExecutorServiceFuture 接口是为了从另一个线程获取返回数据而创建的,而不仅仅是为了运行它。 Future&lt;Void&gt; submit(Runnable task)new Thread(runnable).start() 的作用相同,null 的返回在某些情况下是有意义的。

编辑: 认为您需要在 20 分钟后关闭线程。当你有一个返回值 void 时,你会怎么做?

Future<Void> future = execService.submit(operation);
execService.shutdown();
opResult = future.get(20, TimeUnit.MINUTES);

此代码必须给出错误,因为future 没有返回。但是如果它返回一个空值,execService 控制器对象将知道shutdown 发生了。或者如果它在 20 分钟内没有返回任何东西,则可以使用 execService.shutdownNow()

【讨论】:

如果是Future&lt;Void&gt;,它的工作方式与现在完全相同。 如何从调用方法返回 Void ? Void method() return null; return null 与 void 签名方法不同。 Op 要求没有返回值 首先,我的意思是java.lang.Void(导入后缩写为Void),而不是void,和OP一样。其次,OP 并不要求没有返回值。

以上是关于为啥 ExecutorService.submit(Runnable task) 返回 Future<?> 而不是 Future<Void>?的主要内容,如果未能解决你的问题,请参考以下文章

ExecutorService.submit()与Executor.execute()的区别

executorService.submit(Runnable) 返回的未来对象是不是包含对可运行对象的任何引用?

《Java并发编程实战》第六章 任务运行 读书笔记

Guava Future

157-模拟高并发代码

双重检测机制解决缓存穿透问题