Java-Future学习

2017-03-23  本文已影响0人  Wu巧不成

什么是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作者,希望能早日 达到  接近大神

纽约州立大学Oswego分校计算机科学系的老大爷

再来看看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了。

上一篇下一篇

猜你喜欢

热点阅读