Future和FutureTask的区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Future和FutureTask的区别相关的知识,希望对你有一定的参考价值。
Future是一个接口,FutureTask是Future的一个实现类,并实现了Runnable,因此FutureTask可以传递到线程对象Thread中新建一个线程执行。所以可以通过Excutor(线程池)来执行,也可传递给Thread对象执行。如果在主线程中需要执行比较耗时的操作,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成,当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。
FutureTask是为了弥补Thread的不足而设计的,它可以让程序员准确地知道线程什么时候执行完成并获得到线程执行完成后返回的结果(如果有需要)。
FutureTask是一种可以取消的异步的计算任务。它的计算是通过Callable实现的,它等价于可以携带结果的Runnable,并且有三个状态:等待、运行和完成。完成包括所有计算以任意的方式结束,包括正常结束、取消和异常。
Executor框架利用FutureTask来完成异步任务,并可以用来进行任何潜在的耗时的计算。一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。 参考技术A 区别是:
Future指的是未来。
Future Task指的是未来的任务。
详细解释:
future 英[ˈfju:tʃə(r)] 美[ˈfjutʃɚ]
adj. 将来的,未来的; [语法学] 将来时的;
n. 前途; 期货; [美国俚语] 未婚妻;
[例句]The spokesman said no decision on the proposal was likely in the immediate future.
发言人说近期不会就这项提案作出决议。
task 英[tɑ:sk] 美[tæsk]
n. 作业; 工作,任务; 苦差事;
vt. 交给某人(任务); 使过于劳累;
[例句]Walker had the unenviable task of breaking the bad news to Hill.
沃克不得不把这个坏消息告诉希尔。 参考技术B 将来
将来任务
Java中的Future和FutureTask有啥区别?
【中文标题】Java中的Future和FutureTask有啥区别?【英文标题】:What's the difference between Future and FutureTask in Java?Java中的Future和FutureTask有什么区别? 【发布时间】:2011-06-24 19:36:40 【问题描述】:既然使用ExecutorService
可以submit
一个Callable
任务并返回一个Future
,为什么需要使用FutureTask
包装Callable
任务并使用方法execute
?我觉得他们都做同样的事情。
【问题讨论】:
【参考方案1】:Future
只是接口。在幕后,实现是FutureTask
。
您绝对可以手动使用FutureTask
,但您将失去使用Executor
的优势(池化线程、限制线程等)。使用 FutureTask
与使用旧的 Thread
和使用 run 方法非常相似。
【讨论】:
FutureTask同时实现了Future如果你想改变它的行为或稍后访问它的 Callable,你只需要使用 FutureTask。对于 99% 的使用,只需使用 Callable 和 Future。
【讨论】:
【参考方案3】:其实你是对的。这两种方法是相同的。您通常不需要自己包装它们。如果是这样,您很可能复制了 AbstractExecutorService 中的代码:
/**
* Returns a <tt>RunnableFuture</tt> for the given callable task.
*
* @param callable the callable task being wrapped
* @return a <tt>RunnableFuture</tt> which when run will call the
* underlying callable and which, as a <tt>Future</tt>, will yield
* the callable's result as its result and provide for
* cancellation of the underlying task.
* @since 1.6
*/
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable)
return new FutureTask<T>(callable);
Future 和 RunnableFuture 的唯一区别是 run() 方法:
/**
* A @link Future that is @link Runnable. Successful execution of
* the <tt>run</tt> method causes completion of the <tt>Future</tt>
* and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
* @param <V> The result type returned by this Future's <tt>get</tt> method
*/
public interface RunnableFuture<V> extends Runnable, Future<V>
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
让 Executor 为您构建 FutureTask 的一个很好的理由是确保对 FutureTask 实例的引用不会超过一个。也就是说,Executor拥有这个实例。
【讨论】:
FutureTask.get() 从不抛出 CancellationException,而 Future.get() 会。它是否正确?见docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/…,java.util.concurrent.TimeUnit)。【参考方案4】:FutureTask
这个类提供了一个base implementation of Future
,带有启动和取消计算的方法
Future是接口
【讨论】:
【参考方案5】:Mark 和其他人正确回答Future
是FutureTask
和Executor
的接口,实际上是它的工厂;这意味着应用程序代码很少直接实例化FutureTask
。为了补充讨论,我提供了一个示例,展示了在任何 Executor
之外直接构造和使用 FutureTask
的情况:
FutureTask<Integer> task = new FutureTask<Integer>(()->
System.out.println("Pretend that something complicated is computed");
Thread.sleep(1000);
return 42;
);
Thread t1 = new Thread(()->
try
int r = task.get();
System.out.println("Result is " + r);
catch (InterruptedException | ExecutionException e)
);
Thread t2 = new Thread(()->
try
int r = task.get();
System.out.println("Result is " + r);
catch (InterruptedException | ExecutionException e)
);
Thread t3 = new Thread(()->
try
int r = task.get();
System.out.println("Result is " + r);
catch (InterruptedException | ExecutionException e)
);
System.out.println("Several threads are going to wait until computations is ready");
t1.start();
t2.start();
t3.start();
task.run(); // let the main thread to compute the value
这里,FutureTask
用作同步工具,如CountdownLatch
或类似的屏障原语。它可以通过使用CountdownLatch
或锁和条件重新实现; FutureTask
只是让它很好地封装、不言自明、优雅且代码更少。
还要注意,FutureTask#run() 方法必须在任何线程中显式调用;周围没有执行人为您做这件事。在我的代码中,它最终由主线程执行,但可以修改get()
方法在第一个调用get()
的线程上调用run()
,因此第一个线程到达get()
,它可以是任何一个T1、T2 或 T3 将对所有剩余线程进行计算。
关于这个想法 - 第一个线程请求结果将为其他线程进行计算,而并发尝试将被阻止 - 基于 Memoizer,请参阅“Java 并发实践”中第 108 页的 Memoizer 缓存示例。
【讨论】:
【参考方案6】:如前所述,但不是笼统地说,而是更多的技术术语,因为 FutureTask 实现了 RunnableFuture, 你可以调用它使用
FutureTask<T> result = new FutureTask<T>(new #YourClassImplementingCallable());
Thread t1= new Thread(result);
t1.start();
Object<T> obj = result.get();
这与旧的可运行文件更内联,但它也可以通过回调返回结果。
FutureTask 优于 Future 的强大之处在于它对线程有更多的控制,而不是简单地向 Future 提交一个可调用对象并让执行程序处理线程。
就像你可以在这里调用 t1.join()。
【讨论】:
以上是关于Future和FutureTask的区别的主要内容,如果未能解决你的问题,请参考以下文章
Callable, Runnable, Future, FutureTask