JUC之 FutureTask 源码与工作原理分析

本文详细分析了Java JUC中的FutureTask,讲解了其作为Future模式的实现如何处理异步任务的执行结果。通过FutureTask的状态转变、内部变量waiters的作用以及get、set、cancel方法的源码解读,揭示了任务执行、阻塞与唤醒的机制。此外,还提到了ExecutorService如何处理Runnable和Callable任务,并指出FutureTask在任务完成后的done方法可作为扩展点实现回调功能。
摘要由CSDN通过智能技术生成

JDK1.5 引入了Future模式,Future代表了一个异步任务的执行结果。Future模式可以理解成:主线程将待执行的任务提交给子线程执行后,可以先获取任务结果的持有者Future。然后主线程可以去执行其他的任务。等待到要关注之前任务的执行结果时,再从Future中获取。下面是用户注册的场景。

 

同步实现时,注册接口响应时间150ms= 用户信息保存50ms + 发送短信50ms + 发送邮件50ms

异步实现时,注册接口响应时间100ms= 用户信息保存50ms + max(发送短信50ms, 发送邮件50ms)

Future 接口核心方法

/*尝试取消当前执行的任务*/
boolean cancel(boolean mayInterruptIfRunning);
/*判断当前执行的任务是否被取消*/
boolean isCancelled();
/*判断当前执行的任务是否完成,正常结束、发生异常或任务被取消都认为任务完成*/
boolean isDone();
/*获取当前执行任务对应的结果,将阻塞等待任务执行完*/
V get() throws InterruptedException, ExecutionException;
/*等待一段时间,获取当前执行任务对应的结果,将阻塞等待任务执行完,如果对应时间还未获取结果,
 * 抛出TimeoutException
 */
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

后面所有分析全部基于JDK8

在JDK中Future接口的实现类为FutureTask,其UML图如下。

FutureTask同时实现了Runnable与Future的功能。实现Runnable主要是为了让Executor可以执行,实现Future为了能够持有执行结果的引用

FutureTask的成员变量如下:

/*当前任务的执行状态*/
private volatile int state;
/*当前要执行的任务,执行完后将被设置为null*/
private Callable<V> callable;
/*当前任务的执行结果,当发生异常或被取消时为对应异常,非volatile,由state状态保证线程安全*/
private Object outcome;
/*执行当callable任务的线程引用,为当前线程通过CAS方式原子设置*/
private volatile Thread runner;
/*Treiber椎,用于保存由于调用Future.get方法而阻塞的线程*/
private volatile WaitNode waiters;

先来看一下用于维护当前任务执行状态的state成员变量。

FutureTask内部定义了,任务执行的7种状态。

//任务的初始初始化状态
private static final int NEW          = 0;
//执行结果设置中时,的中间状态
private static final int COMPLETING   = 1;
//任务正常执行完成的最终状态
private static final int NORMAL       = 2;
//任务执行出错的最终状态
private static final int EXCEPTIONAL  = 3;
//调用Future.cancell取消任务的最终状态
private static final int CANCELLED    = 4;
//执行任务的线程被中断的中间状态
private static final int INTERRUPTING = 5;
//执行任务的线程被中断的最终状态
private static final int INTERRUPTED  = 6;

上图展示了,Future任务状态的扭转图。new状态时通过调用set()方法、setException()方法可以使状态最终分别转变为NORMAL与EXCEPTIONAL; new状态时通过调用cancel(flase)方法、cancel(true)方法可以可以使状态最终分别转变为CANCELLED与INTERRUPTED。

再看一下用于保存由于调用Future.get方法而阻塞的线程的Treiber被引用成变量waiters。

static final class WaitNode {
     volatile Thread thread;
     volatile WaitNode next;
     WaitNode() { thread = Thread.currentThread(); }
}

每当一个线程调用Future.get去获取任务的执行结果时,如果当前任务还没有执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倾听铃的声

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值