Future详解

Future模式【1】Future模式是多线程开发中常见的设计模式,它的核心思想是异步调用 。对于Future模式来说,它无法立即返回你需要的数据 , 但是它会返回一个契约,将来你可以凭借这个契约去获取你需要的信息 。
【2】通俗一点就是生产者-消费者模型的扩展 。经典“生产者-消费者”模型中消息的生产者不关心消费者何时处理完该条消息,也不关心处理结果 。Future模式则可以让消息的生产者等待直到消息处理结束 , 如果需要的话还可以取得处理结果 。
java中是如何实现Future模式【1】直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题 就是:没有返回值,也就是不能获取执行完的结果 。
【2】因此java1.5就提供了Callable接口来实现这一场景 , 而Future和FutureTask就可以和Callable接口配合起来使用 。【从而达到Future模式的效果】
Callable和Runnable的区别【1】源码展示
@FunctionalInterfacepublic interface Callable<V> {V call() throws Exception;}@FunctionalInterfacepublic interface Runnable {public abstract void run();}【2】分析说明
Runnable 的缺陷:1.不能返回一个返回值2.不能抛出 checked Exception 。Callable的call方法可以有返回值,可以声明抛出异常 。【3】疑问解析
1)为什么需要 Callable?
Callable 配合 Future 类 可以了解任务执行情况,或者取消任务的执行 , 还可获取任务执行的结果,这些功能都是 Runnable 做不到的 , 因为它没有返回值,不能抛出异常 。
了解Future接口【1】介绍 :Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果 。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果 。
【2】源码展示
public interface Future<V> {// 取消任务的执行 。参数指定是否立即中断任务执行,或者等等任务结束boolean cancel(boolean mayInterruptIfRunning);//任务是否已经取消,任务正常完成前将其取消,则返回trueboolean isCancelled();//需要注意的是如果任务正常终止、异常或取消,都将返回trueboolean isDone();//取得返回对象V get() throws InterruptedException, ExecutionException;//取得返回对像,允许等待设置的时间范围V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}了解FutureTask类(Future接口的实现类)【1】介绍说明
1)该对象相当于是消费者和生产者的桥梁,消费者通过FutureTask存储任务的处理结果,更新任务的状态:未开始、正在处理、已完成等 。而生产者拿到的 FutureTask被转型为Future接口,可以阻塞式获取任务的处理结果 , 非阻塞式获取任务处理状态 。
2)FutureTask既可以被当做Runnable来执行,也可以被当做Future来获取Callable的返回结果 。
【2】代码展示
0)继承关系
public class FutureTask<V> implements RunnableFuture<V> public interface RunnableFuture<V> extends Runnable, Future<V>1)属性值
// 表示当前任务的状态private volatile int state;// 表示当前任务的状态是新创建的,尚未执行private static final int NEW= 0;// 表示当前任务即将结束,还未完全结束 , 值还未写,一种临界状态private static final int COMPLETING= 1;// 表示当前任务正常结束private static final int NORMAL= 2;// 表示当前任务执行过程中出现了异常,内部封装的callable.call()向上抛出异常了private static final int EXCEPTIONAL= 3;// 表示当前任务被取消private static final int CANCELLED= 4;// 表示当前任务中断中private static final int INTERRUPTING = 5;// 表示当前任务已中断private static final int INTERRUPTED= 6;// 我们在使用FutureTask对象的时候,会传入一个Callable实现类或Runnable实现类,这个callable存储的就是// 传入的Callable实现类或Runnable实现类(Runnable会被使用修饰者设计模式伪装为)private Callable<V> callable;// 正常情况下,outcome保存的是任务的返回结果// 不正常情况下 , outcome保存的是任务抛出的异常private Object outcome; // 保存的是当前任务执行期间,执行任务的线程的引用private volatile Thread runner;// 因为会有很多线程去get结果,这里把线程封装成WaitNode , 一种数据结构:栈 , 头插头取private volatile WaitNode waiters;static final class WaitNode {// 线程对象volatile Thread thread;// 下一个WaitNode结点volatile WaitNode next;WaitNode() { thread = Thread.currentThread(); }}2)构造方法
public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW;// ensure visibility of callable}public FutureTask(Runnable runnable, V result) {//封装成callable,但返回值为传入的值this.callable = Executors.callable(runnable, result);this.state = NEW;}

推荐阅读