一、为什么使用Future
jdk提供了Thread和Runnale支持多线程,但是这两种方式执行完任务之后都没有办法获取到执行结果。
jdk1.5之后提供了Future和Callable来解决这个问题,Future方式提供了异步获取执行结果的方式,避免开启任务之后阻塞等待返回结果,而是开启任务之后可以干其他事情异步获取结果。
二、FutureTask
FutureTask实现了RunnableFuture接口,而RunnableFuture接口继承了Runnable和Future接口,所以FutureTask可以作为Runnable被线程执行,也可以通过Callable异步获取任务执行结果。
三、FutureTask源码分析
1.构造方法
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) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
提供了两种构造方法,第二种和第一种的区别在于,第二种执行结果是通过result直接设置进去的,而第一种是通过callable获取的。
2.FutureTask的状态,可以看到有几种状态的定义,以及状态之间的转换。
/**
* The run state of this task, initially NEW. The run state
* transitions to a terminal state only in methods set,
* setException, and cancel. During completion, 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.
*
* Possible state transitions:
* 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;
3.其他属性
// 任务
private Callable<V> callable;
// 执行结果
private Object outcome; // non-volatile, protected by state reads/writes
// 执行任务的线程,用来取消或者中断任务使用
private volatile Thread runner;
// 等待线程,get方法获取执行结果的时候,那么这些线程形成的栈的头部节点就是waiters
private volatile WaitNode waiters;
static final class WaitNode {
volatile Thread thread;
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); }
}
4.CAS辅助工具
// Unsafe mechanics
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);
}
}
4.使用FutureTask示例
FutureTask<Integer> task = new FutureTask<>(()-> {
Thread.sleep(10000L);
return 1;
});
new Thread(task).start();
Integer result = task.get();
5.启动任务,从run方法开始
public void run() {
// 如果状态不是NEW,并且runner已经执行过了(runner旧的值不为null),返回
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 {
// 执行callable得到结果
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result); // 将执行的结果设置给outcome
}
} 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
int s = state;
if (s >= INTERRUPTING)
// 处理可能遗漏的中断
handlePossibleCancellationInterrupt(s);
}
}
protected void setException(Throwable t) {
// 抛出异常
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = t;
// 此处用putOrderedInt而不是CAS,是多线程环境下,可能被其他线程改变了,所以是为了保证状态改为EXCEPTIONAL
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion();
}
}
protected void set(V v) {
// 执行成功
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
// 此处用putOrderedInt而不是CAS,是多线程环境下,可能被其他线程改变了,所以是为了保证状态改为NORMAL
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
private void finishCompletion() {
// assert state > COMPLETING;
// 自旋,直到将waiters清空,并且唤醒waiters栈中所有节点线程
for (WaitNode q; (q = waiters) != null;) {
if (UNSAFE.compareAndSwapObject(this, waitersOffset, 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
}
// 此时状态可能为INTERRUPTING和INTERRUPTED,因为任务可能被其他线程给取消了,此种情况下我们无法判断,所以只能等待任务状态到终止状态
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.
if (s == INTERRUPTING)
while (state == INTERRUPTING) // 挂起线程直到状态修改为INTERRUPTED
Thread.yield(); // wait out pending interrupt
// assert 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();
}
由上述源码分析,run()主要做了以下几件事情
(1).将runner属性设置成当前正在执行run方法的线程
(2).调用callable的call方法执行任务
(3).设置执行结果,若执行成功,将执行结果保存在outcome中;若发生异常,则将异常保存到outcome中,设置结果之前,CAS将状态设置为COMPLETING,设置结果之后,将状态设置为终止态,NORMAL或者EXCEPTIONAL,再将callable设置为null;
(4).唤醒所有的结果查询等待线程,并将waiters清空,将runner设置为null
(5).如果有其他线程取消任务(中断情况),自旋等待中断完成
6.get()获取任务执行结果
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
// 任务还未完成,阻塞等待任务执行状态结果
s = awaitDone(false, 0L);
// 根据任务最终状态,返回结果
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); // 如果执行任务的线程interrupted,将等待获取结果的线程都移除掉(移除的过程中会唤醒所有的等待线程),然后抛出InterruptedException
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
// 任务已经执行到终止状态
return s;
}
else if (s == COMPLETING) // cannot time out yet
Thread.yield(); // 任务已经完成,但是还未设置成终止状态,获取线程自旋等待
else if (q == null)
q = new WaitNode(); // 获取等待节点为空,创建一个节点
else if (!queued) // 节点已经创建,当前任务加入到等待的栈中,queued表示是否成功入栈(因为多线程有竞争)
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); // 未超时,线程挂起
}
else
LockSupport.park(this); // 不带超时的线程挂起
}
}
// 移除等待的线程节点,先将当前节点的thread设置为null,为后续剔除节点做了标记
// 1.如果当前节点在栈顶,那么此时q和pred肯定为null,直接CAS尝试将栈顶设置为下一个节点;如果设置成功,这个地方仍然会再次执行循环,将其他node.thread==null的节点也剔除
// 2.要移除的节点不再栈顶,我们会遍历栈,直到找到node.thread==null的节点,我们将node的前驱节点的next指向node的下一个节点,就将节点剔除掉了。因为存在多线程竞争的情况,pred.thread==null表示该节点被其他线程标记了,下面的节点都是基于该节点,继续遍历没有意义,所以直接从头开始遍历。
private void removeWaiter(WaitNode node) {
if (node != 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 (!UNSAFE.compareAndSwapObject(this, waitersOffset,
q, s))
continue retry;
}
break;
}
}
}
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); // 任务执行异常
}
awaitDown和get方法都没有加锁,state和waiters属性都有加volatile关键字,而对waiters的修改都是使用CAS,保证了线程安全。
7.cancel(),任务可以被其他线程进行取消
public boolean cancel(boolean mayInterruptIfRunning) {
// 任务已经执行过了,任务已经被取消过了,不能再次被取消
if (!(state == NEW &&
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
// 取消任务,并将状态设置为INTERRUPTED
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
} finally {
// 取消任务之后,将获取结果的等待线程都清空
finishCompletion();
}
return true;
}
private void finishCompletion() {
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
if (UNSAFE.compareAndSwapObject(this, waitersOffset, 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
}
来源:oschina
链接:https://my.oschina.net/u/2307176/blog/3196557