1. 常量和变量

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正常执行:NEW -> COMPLETING -> NORMAL
// run异常执行:NEW -> COMPLETING -> EXCEPTIONAL
// cancel(false):NEW -> CANCELLED
// cancel(true):NEW -> INTERRUPTING -> INTERRUPTED private Callable<V> callable; // 任务
private Object outcome; // 执行结果
private volatile Thread runner; // 任务执行线程(在run方法中置为当前线程)
private volatile WaitNode waiters; // 任务等待链表(头节点)

2. 构造方法

public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
} public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result); // RunnableAdapter implements Callable
this.state = NEW;
}

3. 等待节点

static final class WaitNode {
volatile Thread thread; // 等待线程
volatile WaitNode next; // 下一等待节点
WaitNode() { thread = Thread.currentThread(); }
}

4. 实现Future接口

1)cancel

public boolean cancel(boolean mayInterruptIfRunning) {
// 任务状态为NEW && CAS设置state = INTERRUPTING || CANCELLED
if (!(state == NEW && UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try {
if (mayInterruptIfRunning) { // 允许在任务执行时被中断
try {
Thread t = runner;
if (t != null) // 任务尚未执行完毕
t.interrupt(); // 中断任务所在线程
} finally {
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // state = INTERRUPTED
}
}
} finally {
finishCompletion(); // 唤醒所有等待任务执行结果的线程(见get和awaitDone方法)
}
return true;
} private void finishCompletion() {
for (WaitNode q; (q = waiters) != null;) { // 从头节点(q)开始遍历waiters链表
if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { // CAS设置waiters链表为空
for (;;) {
Thread t = q.thread;
if (t != null) {
q.thread = null; // 标记节点q被唤醒
LockSupport.unpark(t);
// 唤醒线程
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null;
q = next;
}
break;
}
}
done(); // noop
callable = null;
} protected void done() { }

2)isCancelled和isDone

public boolean isCancelled() { // 任务是否已取消执行
return state >= CANCELLED;
} public boolean isDone() { // 任务是否执行完毕(对外如此,对内是 <= COMPLETING)
// cancel方法直接设置任务状态为INTERRUPTING || CANCELLED,run方法中在set执行结果时设置任务状态为COMPLETING
return state != NEW;
}

3)get

public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L); // 永久等待
return report(s);
} public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null)
throw new NullPointerException();
int s = state;
// 在timeout时间内等待
if (s <= COMPLETING && (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
throw new TimeoutException();
return report(s);
} private int awaitDone(boolean timed, long nanos) throws InterruptedException {
final long deadline = timed ? System.nanoTime() + nanos : 0L; // 计算截止时间
WaitNode q = null;
boolean queued = false;
for (;;) {
if (Thread.interrupted()) { // 检查清除中断,移除等待节点,抛出异常
removeWaiter(q);
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) { // 任务执行完毕
if (q != null) // 已建立任务等待节点
q.thread = null;
return s;
}
else if (s == COMPLETING) // 任务执行中
Thread.yield();
else if (q == null) // 任务尚未执行(s == NEW),则建立任务等待节点q
q = new WaitNode();
else if (!queued) // q尚未排队,则CAS设置q为头节点
queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);
else if (timed) { // 定时等待
nanos = deadline - System.nanoTime();
if (nanos <= 0L) { // 超时,则移除所有已被唤醒的节点
removeWaiter(q);
return state;
}
LockSupport.parkNanos(this, nanos); // 在naos时间内等待
}
else
LockSupport.park(this); // 永久等待
}
} private void removeWaiter(WaitNode node) {
if (node != null) {
node.thread = null;
retry:
for (;;) {
// pred被唤醒 || CAS(waiters)失败:回到此处
for (WaitNode pred = null, q = waiters, s; q != null; q = s) { // 从头节点(q)开始遍历waiters链表
s = q.next;
if (q.thread != null) // q未被唤醒
pred = q;
else if (pred != null) { // q已被唤醒 && q前存在未被唤醒节点
pred.next = s; // 在链表中删除p
if (pred.thread == null) // pred被唤醒(其它线程正在同步finishCompletion:cancel || run) || pred超时(其它线程正在同步removeWaiter)
continue retry;
}
// q已被唤醒 && q前不存在未被唤醒节点,则CAS设置头节点为q.next
else if (!UNSAFE.compareAndSwapObject(this, waitersOffset, q, s))
continue retry;
}
break;
}
}
}

5. 实现Runnable接口

public void run() {
// 任务未开始执行 || CAS设置runner = Thread.currentThread失败
if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, 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)
set(result); // 设置正常的执行结果
}
} finally {
runner = null;
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s); // 任务可能正在被其它线程cancel:等待cancel的完成
}
} protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { // CAS设置state = COMPLETING(任务可能已被cancel)
// CAS(state)成功
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // state = NORMAL
finishCompletion(); // 唤醒所有任务等待节点
}
} protected void setException(Throwable t) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { // CAS设置state = COMPLETING(任务可能已被cancel)
// CAS(state)成功
outcome = t;
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // state = EXCEPTIONAL
finishCompletion(); // 唤醒所有任务等待节点
}
} private void handlePossibleCancellationInterrupt(int s) {
if (s == INTERRUPTING)
while (state == INTERRUPTING)
Thread.yield();
}

6. Unsafe

private static final sun.misc.Unsafe UNSAFE;
private static final long stateOffset;
private static final long runnerOffset;
private static final long waitersOffset;
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> k = FutureTask.class;
stateOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("state"));
runnerOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("runner"));
waitersOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("waiters"));
} catch (Exception e) {
throw new Error(e);
}
}

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

  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. FutureTask源码分析(JDK7)

    总览 A cancellable asynchronous computation. This class provides a base implementation of {@link Futur ...

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

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

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

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

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

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

  8. 线程之Callable、Future 和FutureTask使用及源码分析

    一.Callable 我们知道启动线程有以下两种方式(jdk源码注释中官方定义只有两种启动方式,callable不算线程启动方式) 原文链接:http://www.studyshare.cn/blog ...

  9. android高级---->AsyncTask的源码分析

    在Android中实现异步任务机制有两种方式,Handler和AsyncTask,它在子线程更新UI的例子可以参见我的博客(android基础---->子线程更新UI).今天我们通过一个小的案例 ...

随机推荐

  1. OSI与TCP/IP各层的结构与功能,都有哪些协议

    前言: 今天更新一下计算机网络的一些非常重要的知识,可能很多人都不知学计算机网络有什么用,我想说的是它真的比较重要,像咱们学校只要是学计算机这个专业都要学习这门课程.另外大家要是去一些像BAT,阿里, ...

  2. ThinkPHP5 模型 - 事务支持

    使用事务之前,先确保数据库的存储引擎支持事务操作. MyISAM:不支持事务,主要用于读数据提高性能 InnoDB:支持事务.行级锁和并发 Berkeley DB:支持事务 ThinkPHP5 使用事 ...

  3. 用tkinter实现的gui小工具

    import tkinter import requests import json from tkinter import * class FindLocation(object): def __i ...

  4. 64_m1

    MAKEDEV-3.24-18.fc26.x86_64.rpm 13-Feb-2017 22:33 101030 MUMPS-5.0.2-8.fc26.i686.rpm 14-Feb-2017 13: ...

  5. iOS WKWebView ios9以上版本配置 与 设置UserAgent(用户代理), 解决点击web, 客户端接收不到web事件问题

    项目运行在ios9上需要在info.plist文件中配置加入如下信息, App Transport Security Settings Allow Arbitrary Loads = YES < ...

  6. Android IPC

    1. 什么是Android IPC IPC:inter-process Commnication跨进程的通信,多进程之间的通信,不同的操作系统有不同的通信方式,Android继承自Linux,但其IP ...

  7. JS如何获取Input的name或者ID?

    <input name="music" type="image" id="music" onclick="loadmusic ...

  8. maven使用备忘

    maven的所有功能本质上都是通过插件来实现的所有的功能.archetype插件就是根据项目类型创建项目的插件.执行archetype:generate命令就会list一系列的项目类型,可以选择一个合 ...

  9. php文件上传需要的配置

    服务端配置(php.ini) 1.file_uploads=On  //支持HTTP上传 2.upload_tmp_dir =”” //临时文件保存的目录 3.upload_max_filesize ...

  10. JAVA版数据库主键ID生成器

    import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public clas ...