什么是Future?干什么的解决什么问题?在什么情况使用?
带着问题,我们去看看。
首先,Future对象是一个异步计算的结果,而在Callable任务中可以拿到这个Future的对象。那同样是run执行,为什么Runable没有这个对象?
这还是一个设计思路的问题,google希望我们执行一个普通的任务的时候,大家都去用Runable就好了,执行完系统就帮你销毁了,而当我们需要得到一个Future的时候,意味着我们的使用场景不同了,我们需要他来帮我们分析任务在执行过程中出现了哪些状况。
也就是说Runable没必要有返回值,因为我已经有一个更适合的角色Future帮我去做这件事了,设计就是如此。
Future这个接口
interface Future<V> 泛型未知,需要我们传递一个指定的类型
看一下源码的注释
* @see FutureTask
* @see Executor
* @since 1.5
* @author Doug Lea
* @paramThe result type returned by this Future's {@code get} method
1.see 提示我们参考FutureTask 和 Executor
2.实现版本java1.5版本
3.分享者Doug Lea,对Java影响力最大的个人,util.concurrent包的来源
我们可以瞻仰一下Doug Lea作者,希望能早日 达到 接近大神
再来看看concurrent包下的内容,难以想象人家的大脑到底装了些什么,没有对比就没有伤害。
Future接口方法
boolean cancel(boolean mayInterruptIfRunning);
mayInterruptIfRunning参数的字面含义是“可能中断运行”,他有很多情况,为什么会有这么多种情况还要参见FutureTask中的定义
1.如果任务已经执行完毕,那么返回false。
2.如果任务已经取消,那么返回false。
3.如果任务已经停止,则cancel()方法会返回true。
4.mayInterruptIfRunning是否中断其运行,设置ture中断,否者任务将继续运行直到结束。
5.此方法返回后任务要么处于运行结束状态,要么处于取消状态。isDone()将永远返回true,如果cancel()方法返回true,isCancelled()始终返回true。
boolean isCancelled();
是否被取消,如果计算在正常结束前被取消了,则返回true
boolean isDone();
是否完成
V get() throws InterruptedException, ExecutionException;
返回结果,如果计算未完成,则等待任务完成,计算被取消抛的异常和执行时异常
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
设置一个等待时间,超时会抛异常,比上面的方法多出一个超时的异常。
总结一下就是:Future就是对Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果()为止。
FutureTask
Future主要通过FutureTask结合线程池来使用。FutureTask实现了RunnableFuture接口(1.6版本出现),而RunnableFuture又同时实现了Runnable和Future<V>接口,意味着可以交给Executor执行,这里很有趣的是,既然RunnableFuture是1.6才出来,换言之在1.5出现线程池的时候调用方式只能在FutureTask中通过.run()来运行。
我们先看看FutureTask中构造方法。
publicFutureTask(Runnable runnable,Vresult) {
this.callable= Executors.callable(runnable, result);
this.state=NEW;// ensure visibility of callable
}
初始化状态为NEW,下面是状态的设置0-6。
private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
run() 方法中执行成功调用set(状态),执行失败抛异常,如下。
if(c !=null&&state==NEW) {
Vresult;
booleanran;
try{
result = c.call();
ran =true;
}catch(Throwable ex) {
result =null;
ran =false;
setException(ex);
}
if (ran)
set(result);
set方法中把状态设置成COMPLETING 然后设置成NORMAL,换言之run()执行完毕状态都会改变,不再为NEW了,如下。
protected void set(Vv) {
if(UNSAFE.compareAndSwapInt(this,stateOffset,NEW,COMPLETING)) {
outcome= v;
UNSAFE.putOrderedInt(this,stateOffset,NORMAL);// final state
finishCompletion();
}
}
接着是cancel()方法中设为ture时把状态 NEW->INTERRUPTING ->INTERRUPTED,cancel()为false的状态变化就是NEW->=CANCELLED。
cancel()方法仅仅只是改变了futureTask的状态位并没有起到结束进程的作用,这是为什么呢?
我们看看future.get()方法可知,如果一个futureTask被cancel()了,调用get()方法会抛出CancellationException。也就是说cancel(true)方法也只是希望当前线程可以响应中断而已,当线程被阻塞,抛出InterruptedException。也就可以解释的通为什么future的方法
boolean cancel(boolean mayInterruptIfRunning) 中定义为什么取名为mayInterruptIfRunning了。