Java中的Future和FutureTask有什么区别?
既然使用ExecutorService
可以提交
一个Callable
任务并返回一个Future
,为什么需要使用FutureTask< /code> 包装
Callable
任务并使用方法 execute
?我觉得他们都做同样的事情。
Since use ExecutorService
can submit
a Callable
task and return a Future
, why need to use FutureTask
to wrap Callable
task and use the method execute
? I feel they both do the same thing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
FutureTask
此类提供了Future的基本实现,以及启动和取消计算的方法
Future 是接口
FutureTask
This class provides a
base implementation of Future
, with methods to start and cancel a computationFuture is the interface
事实上你是对的。这两种方法是相同的。您通常不需要自己包装它们。如果是,您可能会重复 AbstractExecutorService 中的代码:
Future 和 RunnableFuture 之间的唯一区别是 run() 方法:
让 Executor 为您构造 FutureTask 的一个很好的理由是确保没有可能的方法对 FutureTask 实例存在多个引用。也就是说,执行者拥有这个实例。
In fact you are correct. The two approaches are identical. You generally don't need to wrap them yourself. If you are, you're likely duplicating the code in AbstractExecutorService:
The only difference between Future and RunnableFuture, is the run() method:
A good reason to let the Executor construct the FutureTask for you is to ensure that there is no possible way more than one reference exists to the FutureTask instance. That is, the Executor owns this instance.
Future
只是接口。在幕后,实现是FutureTask。您绝对可以手动使用
FutureTask
,但您将失去使用Executor
的优势(池化线程、限制线程等)。使用FutureTask
与使用旧的Thread
和使用 run 方法非常相似。Future
is just interface. Behind the scene, the implementation isFutureTask
.You can absolutely use
FutureTask
manually but you will lose the advantages of usingExecutor
(pooling thread, limit the thread, etc). UsingFutureTask
is quite similar to using the oldThread
and using the run method.仅当您想更改其行为或稍后访问其 Callable 时,才需要使用 FutureTask。对于 99% 的使用,只需使用 Callable 和 Future。
You would only need to use FutureTask if you want to change its behaviour or access its Callable later. For 99% of uses, just use Callable and Future.
正如 Mark 和其他人正确回答的那样,Future 是 FutureTask 的接口,而 Executor 实际上是它的工厂;这意味着应用程序代码很少直接实例化
FutureTask
。为了补充讨论,我提供了一个示例,展示了在任何Executor
之外直接构造和使用FutureTask
的情况:这里使用了
FutureTask
作为同步工具,例如 CountdownLatch 或类似的屏障原语。它可以通过使用 CountdownLatch 或锁和条件来重新实现;FutureTask
只是使其封装得很好、不言自明、优雅且代码更少。另请注意,必须在任何线程中显式调用 FutureTask#run() 方法;周围没有执行者可以为您做这件事。在我的代码中,它最终由主线程执行,但是可以修改
get()
方法以在第一个调用get() 的线程上调用
,因此第一个到达run()
)get()
的线程(可以是 T1、T2 或 T3 中的任何一个)将为所有剩余线程执行计算。基于这个想法 - 第一个请求结果的线程将为其他线程进行计算,而并发尝试将被阻止 - 基于 Memoizer,请参阅“Java 并发实践”中第 108 页的 Memoizer 缓存示例。
As Mark, and others, correctly answered that
Future
is the interface forFutureTask
andExecutor
effectively its factory; meaning that application code rarely instantiatesFutureTask
directly. To complement the discussion I am providing an example showing a situation whereFutureTask
is constructed and used directly, outside anyExecutor
:Here,
FutureTask
is used as a synchronization tool, likeCountdownLatch
or similar barrier primitive. It could have been re-implemented by usingCountdownLatch
or locks and conditions;FutureTask
just makes it nicely encapsulated, self-explanatory, elegant and with less code.Also note that FutureTask#run() method must be called explicitly, in any of the threads; there no Executor around to do it for you. In my code, it is eventually executed by the main thread, but one can modify
get()
method to callrun()
on the first thread callingget()
, therefore the first thread reachingget()
, and it can be any of T1, T2 or T3, would do the calculation for all remaining threads.On this idea - first thread requesting result would do the calculation for others, while concurrent attempts would be blocked - is based Memoizer, see Memoizer Cache example from page 108 in "Java Concurrency in Practice".
正如已经提到的,但不是笼统地说,而是更多技术术语,因为 FutureTask 实现了 RunnableFuture,
您可以使用它来调用它,
这与旧的可运行程序更加内联,但它也能够通过回调返回结果。
FutureTask 相对于 Future 的强大之处在于,它对线程有更多的控制权,而不是简单地向 Future 提交可调用对象并让执行器处理线程。
就像你可以在这里调用 t1.join() 一样。
As already mentioned , but speaking not in general but in more of technical terms, since FutureTask implements RunnableFuture,
you can call it using
This is more inline with older runnable but it also has the capacity to return result via callback.
The greater power of FutureTask over Future lies in the fact that it has more control over threads as against just simply Submitting a callable to Future and let executor handle the threads.
like you can call here t1.join().