总览

    A cancellable asynchronous computation.
This class provides a base implementation of {@link Future}, with methods to start and cancel a computation, query to see if the computation is complete, and retrieve the result of the computation.
The result can only be retrieved when the computation has completed; the {@code get} methods will block if the computation has not yet completed.
Once the computation has completed, the computation cannot be restarted or cancelled (unless the computation is invoked using {@link #runAndReset}).

FututeTask 是可取消的异步任务。这个类提供了 Future 的基本实现,通过这些实现的方法能够开始或取消任务、查询任务是否完成、获取任务结果。仅当任务完成时才能获取任务的结果;当任务未完成时, get() 会阻塞。一旦任务完成,任务不能被重启或取消(除非任务由 runAndReset() 来启动)。

//@param <V> 是 get() 返回结果的类型
public class FutureTask<V> implements RunnableFuture<V>

和JDK7以前的版本的不同之处

/*
* Revision notes: This differs from previous versions of this
* class that relied on AbstractQueuedSynchronizer, mainly to
* avoid surprising users about retaining interrupt status during
* cancellation races.
* Sync control in the current design relies
* on a "state" field updated via CAS to track completion, along
* with a simple Treiber stack to hold waiting threads.
*/

和之前依赖AQS的版本不同的主要原因是,之前的版本在并发的情况下取消任务,可能会导致任务处于 interrupt 的状态。

当前设计的同步控制依赖于通过CAS更新的 state 成员变量以及一个容纳等待线程的 Treiber stack 来追踪任务的完成情况。

成员变量

/**
* The run state of this task, initially NEW. The run state
* transitions to a terminal state only in methods set,
* setException, and cancel. During comp letion, state may take on
* transient values of COMPLETING (while outcome is being set) or
* INTERRUPTING (only while interrupting the runner to satisfy a
* cancel(true)). Transitions from these intermediate to final
* states use cheaper ordered/lazy writes because values are unique
* and cannot be further modified.
* 此任务的运行状态,初始值是NEW。
* 运行状态转换只可能在set(), setException()和cancel()方法中发生。
* 任务正在完成时,状态可能处于 COMPLETING(正在设置outcome成员变量) 或 INTERRUPTING(当通过
* cancel(ture)中断运行线程时) 这2个中间状态(瞬时值)。
*
* 可能发生的状态转换:
* NEW -> COMPLETING -> NORMAL
* NEW -> COMPLETING -> EXCEPTIONAL
* NEW -> CANCELLED
* NEW -> INTERRUPTING -> INTERRUPTED
*/
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; /** The underlying callable; nulled out after run */
//运行后将变为null
private Callable<V> callable;
/** The result to return or exception to throw from get() */
//get()返回的结果或抛出的异常
//非volatile,受state的读或写保护
private Object outcome; // non-volatile, protected by state reads/writes
/** The thread running the callable; CASed during run() */
//运行当前callable的线程
private volatile Thread runner;
/** Treiber stack of waiting threads */
//容纳等待线程的栈
private volatile WaitNode waiters;

构造函数

 /**
* Creates a {@code FutureTask} that will, upon running, execute the
* given {@code Callable}.
* 创建一个在运行时会执行指定callable的FutureTask
*
* @param callable the callable task
* @throws NullPointerException if the callable is null
*/
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
} /**
* Creates a {@code FutureTask} that will, upon running, execute the
* given {@code Runnable}, and arrange that {@code get} will return the
* given result on successful completion.
* 创建一个在运行时执行指定Runnable的,能够令get()在成功完成时返回结果的FutureTask
*
* @param runnable the runnable task
* @param result the result to return on successful completion. If
* you don't need a particular result, consider using
* constructions of the form:
* {@code Future<?> f = new FutureTask<Void>(runnable, null)}
* @throws NullPointerException if the runnable is null
*/
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}

成员方法



public boolean isCancelled() {
return state >= CANCELLED;
} public boolean isDone() {
return state != NEW;
} /**
* Returns result or throws exception for completed task.
* 为完成的任务返回结果或抛出异常
*
* @param s completed state value
*/
@SuppressWarnings("unchecked")
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
} public boolean cancel(boolean mayInterruptIfRunning) {
//只有在NEW状态的任务才可以被取消
if (!(state == NEW && STATE.compareAndSet
(this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
//设置中断
t.interrupt();
} finally { // final state
//设置为最终状态:被中断
STATE.setRelease(this, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
} /**
* @throws CancellationException {@inheritDoc}
*/
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
} /**
* @throws CancellationException {@inheritDoc}
*/
public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null)
throw new NullPointerException();
int s = state;
//若任务未完成,等待任务完成
if (s <= COMPLETING &&
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
throw new TimeoutException();
return report(s);
} /**
* Protected method invoked when this task transitions to state
* {@code isDone} (whether normally or via cancellation). The
* default implementation does nothing. Subclasses may override
* this method to invoke completion callbacks or perform
* bookkeeping. Note that you can query status inside the
* implementation of this method to determine whether this task
* has been cancelled.
*
* 受保护方法。
* 子类可以重写这个方法来进行任务回调或者记录状态。
* 你可以通过在方法的实现中查询任务的状态来判断任务是否被取消。
*/
protected void done() { } /**
* Sets the result of this future to the given value unless
* this future has already been set or has been cancelled.
* 将任务的结果设置为给定值,除非这个任务以及被设置或被取消。
*
* <p>This method is invoked internally by the {@link #run} method
* upon successful completion of the computation.
*
* @param v the value
*/
protected void set(V v) {
if (STATE.compareAndSet(this, NEW, COMPLETING)) {
outcome = v;
//设置最终状态:正常完成
STATE.setRelease(this, NORMAL); // final state
finishCompletion();
}
} /**
* Causes this future to report an {@link ExecutionException}
* with the given throwable as its cause, unless this future has
* already been set or has been cancelled.
* 导致任务将报告一个以值得throwable为原因的 ExecutionException,
* 除非任务已经被设置结果或被取消。
*
* <p>This method is invoked internally by the {@link #run} method
* upon failure of the computation.
* 这个是一个内部使用的方法,只在任务失败时由run()调用。
*
* @param t the cause of failure
*/
protected void setException(Throwable t) {
if (STATE.compareAndSet(this, NEW, COMPLETING)) {
outcome = t;
STATE.setRelease(this, EXCEPTIONAL); // final state
finishCompletion();
}
} public void run() {
//以下2种情况直接返回:
//1.状态不为NEW
//2.CAS设置当前线程为任务运行线程失败
if (state != NEW ||
!RUNNER.compareAndSet(this, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
//这个方法会调用finishCompletion()改变任务状态
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
// 防止cacel(true)的线程挂起导致中断不完全,
// 从而处于Interrupting的中间状态。
// 保证 interrupting 这出现在run和runAndSet方法中
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
} /**
* Executes the computation without setting its result, and then
* resets this future to initial state, failing to do so if the
* computation encounters an exception or is cancelled. This is
* designed for use with tasks that intrinsically execute more
* than once.
* 在不设置结果的前提下运行任务,然后将future设置成初始状态?
* 当任务遇到异常或被取消,将会运行失败。
*
* 此方法设计目的:服务那些本就需要执行多次的任务。
* 在ScheduleThreadPoolExecutor中用到,因为里面的任务都是定时或周期执行的,需要被执行多次。
*
* @return {@code true} if successfully run and reset
*/
protected boolean runAndReset() {
//仅仅指出和run()的不同之处
if (state != NEW ||
!RUNNER.compareAndSet(this, null, Thread.currentThread()))
return false;
boolean ran = false;
int s = state;
try {
Callable<V> c = callable;
if (c != null && s == NEW) {
try {
c.call(); // don't set result 这里没有接收结果
ran = true;
} catch (Throwable ex) {
setException(ex);
}
//这里没有调用set(),因此不会调用finishCompletion()改变任务状态
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
return ran && s == NEW;
} /**
* Ensures that any interrupt from a possible cancel(true) is only
* delivered to a task while in run or runAndReset.
* 保证 interrupting 这出现在run和runAndSet方法中。
*/
private void handlePossibleCancellationInterrupt(int s) {
// It is possible for our interrupter to stall before getting a
// chance to interrupt us. Let's spin-wait patiently.
// 若任务处于INTERRUPTING状态,自旋等待任务被完全中断,
// 即等待转换到INTERRUPTED状态
if (s == INTERRUPTING)
while (state == INTERRUPTING)
Thread.yield(); // wait out pending interrupt // assert state == INTERRUPTED;
// 到这里 state必然等于INTERRUPTED // We want to clear any interrupt we may have received from
// cancel(true). However, it is permissible to use interrupts
// as an independent mechanism for a task to communicate with
// its caller, and there is no way to clear only the
// cancellation interrupt.
//
// Thread.interrupted();
} /**
* Simple linked list nodes to record waiting threads in a Treiber
* stack. See other classes such as Phaser and SynchronousQueue
* for more detailed explanation.
* 普通节点,作为栈节点记录栈中的等待线程
*/
static final class WaitNode {
volatile Thread thread;
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); }
} /**
* Removes and signals all waiting threads, invokes done(), and
* nulls out callable.
* 移除和通知所有等待的线程,调用done(),并移除callable。
*/
private void finishCompletion() {
// assert state > COMPLETING;
// 此时 state > COMPLETING; //若等待线程栈非空
for (WaitNode q; (q = waiters) != null;) {
//CAS设置等待线程为null
if (WAITERS.weakCompareAndSet(this, q, null)) {
//迭代栈,唤醒所有非空线程
for (;;) {
Thread t = q.thread;
if (t != null) {
q.thread = null;
//唤醒
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc
q = next;
}
break;
}
} done(); callable = null; // to reduce footprint
} /**
* Awaits completion or aborts on interrupt or timeout.
* 等待任务完成或在中断和超时的情况下放弃任务
*
* @param timed true if use timed waits
* 当需要超时等待的功能时为真
* @param nanos time to wait, if timed
* @return state upon completion or at timeout
* 返回任务完成或任务超时的状态
*/
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
// The code below is very delicate, to achieve these goals:
// - call nanoTime exactly once for each call to park
// - if nanos <= 0L, return promptly without allocation or nanoTime
// - if nanos == Long.MIN_VALUE, don't underflow
// - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
// and we suffer a spurious wakeup, we will do no worse than
// to park-spin for a while
long startTime = 0L; // Special value 0L means not yet parked
WaitNode q = null;
//记录当前线程是否入栈排队
boolean queued = false;
for (;;) {
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
else if (s == COMPLETING)
// We may have already promised (via isDone) that we are done
// so never return empty-handed or throw InterruptedException
Thread.yield();
else if (Thread.interrupted()) {
//若当前线程被中断,移出栈,抛出异常
removeWaiter(q);
throw new InterruptedException();
}
else if (q == null) {
if (timed && nanos <= 0L)
return s;
//创建栈节点
q = new WaitNode();
}
else if (!queued)
//节点CAS尝试入栈,若成功则此节点成为waiters
queued = WAITERS.weakCompareAndSet(this, q.next = waiters, q);
else if (timed) {
//若需要超时等待的功能
final long parkNanos;
if (startTime == 0L) { // first time
//首次判断,记录开始时间
startTime = System.nanoTime();
if (startTime == 0L)
startTime = 1L;
parkNanos = nanos;
} else {
long elapsed = System.nanoTime() - startTime;
if (elapsed >= nanos) {
//若超时则返回
removeWaiter(q);
return state;
}
//计算剩余等待时间
parkNanos = nanos - elapsed;
}
// nanoTime may be slow; recheck before parking
if (state < COMPLETING)
//快速判断任务是否正在完成
LockSupport.parkNanos(this, parkNanos);
}
else
//若不需要超时等待的功能,直接阻塞
LockSupport.park(this);
}
} /**
* Tries to unlink a timed-out or interrupted wait node to avoid
* accumulating garbage. Internal nodes are simply unspliced
* without CAS since it is harmless if they are traversed anyway
* by releasers. To avoid effects of unsplicing from already
* removed nodes, the list is retraversed in case of an apparent
* race. This is slow when there are a lot of nodes, but we don't
* expect lists to be long enough to outweigh higher-overhead
* schemes.
* 尝试移除超时或被中断的节点。
* 在明显竞争时将会重新遍历列表,目的是为了避免移除一个已经移除的节点。
*/
private void removeWaiter(WaitNode node) {
if (node != null) {
//令当前节点的线程为null
node.thread = null;
retry:
for (;;) { // restart on removeWaiter race
for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
s = q.next;
if (q.thread != null)
pred = q;
else if (pred != null) {
//若当前线程为空,但存在前继非空节点,则移除当前节点
pred.next = s;
//若前继节点无效,则重新遍历
if (pred.thread == null) // check for race
continue retry;
}
else if (!WAITERS.compareAndSet(this, q, s))
//移除栈顶节点失败
continue retry;
}
break;
}
}
} /**
* Returns a string representation of this FutureTask.
*
* @implSpec
* The default implementation returns a string identifying this
* FutureTask, as well as its completion state. The state, in
* brackets, contains one of the strings {@code "Completed Normally"},
* {@code "Completed Exceptionally"}, {@code "Cancelled"}, or {@code
* "Not completed"}.
*
* @return a string representation of this FutureTask
*/
public String toString() {
final String status;
switch (state) {
case NORMAL:
status = "[Completed normally]";
break;
case EXCEPTIONAL:
status = "[Completed exceptionally: " + outcome + "]";
break;
case CANCELLED:
case INTERRUPTING:
case INTERRUPTED:
status = "[Cancelled]";
break;
default:
final Callable<?> callable = this.callable;
status = (callable == null)
? "[Not completed]"
: "[Not completed, task = " + callable + "]";
}
return super.toString() + status;
} // VarHandle mechanics
private static final VarHandle STATE;
private static final VarHandle RUNNER;
private static final VarHandle WAITERS;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
STATE = l.findVarHandle(FutureTask.class, "state", int.class);
RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class);
WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class);
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
} // Reduce the risk of rare disastrous classloading in first call to
// LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
Class<?> ensureLoaded = LockSupport.class;
}

FutureTask源码分析(JDK7)的更多相关文章

  1. FutureTask 源码分析

    FutureTask 源码分析,这个类的原理与我分析android当中的FutureTask类差不多[http://www.cnblogs.com/daxin/p/3802392.html] publ ...

  2. Java并发编程笔记之FutureTask源码分析

    FutureTask可用于异步获取执行结果或取消执行任务的场景.通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过Fu ...

  3. 并发编程—— FutureTask 源码分析

    1. 前言 当我们在 Java 中使用异步编程的时候,大部分时候,我们都会使用 Future,并且使用线程池的 submit 方法提交一个 Callable 对象.然后调用 Future 的 get ...

  4. TreeSet与TreeMap的源码分析 JDK7

    TreeSet存储原则是:不可重复,有序的. public TreeSet() { this(new TreeMap<E,Object>()); } public TreeSet(Comp ...

  5. FutureTask源码分析

    1. 常量和变量 private volatile int state; // 任务状态 private static final int NEW = 0; private static final ...

  6. JUC源码分析-线程池篇(二)FutureTask

    JUC源码分析-线程池篇(二)FutureTask JDK5 之后提供了 Callable 和 Future 接口,通过它们就可以在任务执行完毕之后得到任务的执行结果.本文从源代码角度分析下具体的实现 ...

  7. Java 多线程(五)—— 线程池基础 之 FutureTask源码解析

    FutureTask是一个支持取消行为的异步任务执行器.该类实现了Future接口的方法. 如: 取消任务执行 查询任务是否执行完成 获取任务执行结果(”get“任务必须得执行完成才能获取结果,否则会 ...

  8. HashMap实现原理及源码分析之JDK7

    攻克集合第一关!! 转载 http://www.cnblogs.com/chengxiao/ 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如m ...

  9. Java异步编程——深入源码分析FutureTask

    Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...

随机推荐

  1. Codeforces Round #651 (Div. 2) E. Binary Subsequence Rotation(dp)

    题目链接:https://codeforces.com/contest/1370/problem/E 题意 给出两个长为 $n$ 的 $01$ 串 $s$ 和 $t$,每次可以选择 $s$ 的一些下标 ...

  2. HDOJ 3398

    这个题坑了太久太久啊!!!!!贡献了得有30+WA才发现 原来是因为在乘法中有溢出导致一直TLE啊.... 但是到最后也不知道有个问题怎么解决的. 就是在getp()中的num值的诡异的改变! #in ...

  3. Codeforces Round #692 (Div. 2, based on Technocup 2021 Elimination Round 3) C. Peaceful Rooks (思维,dsu找环)

    题意:一个棋盘上有一些"车",现在要让这些"车"跑到左倾斜的对角线上,每次可以移动一个棋子,但是棋盘的任意时刻都不能出现一个"车"能吃另一个 ...

  4. 使用Github+jsDelivr搭建图床和存储服务

    使用元素 我的博客NLNet 并未搭建自己的博客,使用博客园(cnblogs),自定义了主题NLNet-Theme. 写作工具Typora 优秀的Markdown编辑器.参考NLNet-Theme,我 ...

  5. 14. 从0学ARM-exynos4412-看门狗裸机程序编写

    看门狗 一.概念 看门狗的简称是WDT(Watch Dog Timer),exynos4412scp中的看门狗定时器(WDT)是一种定时装置. 1. 工作原理 由(一般需要客户编写)软件读写定时器相关 ...

  6. kubernetes进阶(六)k8s平滑升级

    当我们遇到K8S有漏洞的时候,或者为了满足需求,有时候可能会需要升级或者降级版本, 为了减少对业务的影响,尽量选择在业务低谷的时候来升级: 首先准备好文件:我这里选择的是内网文件服务器上下载的,请自行 ...

  7. C# 特殊符号

    特殊符号 @开头 前面提到过,字符串里免转义用的, 字符串里写的啥就是啥,遇到\ 不转义 ?? 判断一个值是不是null,是的话就变成后面的默认值,不是的话就还是原值 $开头 字符串篡改 和forma ...

  8. u-boot 移植 --->7、u-bootl流程粗线条梳理

    通过前面的调试了解到s5pv210这个芯片的启动流程是需要将u-boot分为两部分的分别为SPL和u-boot.这里我使用网上的方式不直接使用u-boot的SPL连接脚本单独生成SPL的image而是 ...

  9. ARM汇编--汇编中符号和变量

    习惯了使用C语言的情况下我发现自己对与汇编程序的符号和变量的理解很不深刻,今天抽空来学学加深理解.以ARM汇编来说,在汇编代码中所有以"."开头的指令都是汇编伪指令,他们不属于AR ...

  10. Linux 驱动框架---驱动中的时间相关

    内核中的时间 Linux 系统内核对于时间的管理依赖于硬件,硬件按一定的周期产生中断,周期由内核的一个配置值HZ决定在系统启动时会将定时器配置为HZ值指定的频率产生中断:同时内核和维护一个64位(X8 ...