FutureTask 源码解析

114 阅读6分钟
Future 结合线程池,可以异步执行任务并且获取返回值,实际使用中也有很多场景,下面对Future实现类 FutureTask注释解析。
最后有关于线程池使用FutureTask.get() 可能导致的问题。

源码备注解析


public class FutureTask<V> implements RunnableFuture<V> {  

/**  
* 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// set() setException() 方法触发时也就是有执行结果后,转换为该状态  
private static final int NORMAL = 2// set() 方法如果修改状态COMPLETING成功后,则在此转换为该状态  
private static final int EXCEPTIONAL = 3// set() 方法如果修改状态COMPLETING成功后,则在此转换为该状态  
private static final int CANCELLED = 4// 4/5/6 状态为关闭 cancel(true) 方法触发时转换为该状态  
private static final int INTERRUPTING = 5// cancel(true) 则会触发为该状态  
private static final int INTERRUPTED = 6// cancel(true) 则会触发为该状态  
  
/** The underlying callable; nulled out after running */  
private Callable<V> callable; // 执行任务的 callable/** The result to return or exception to throw from get() */  
// 任务返回信息,可能是结果值,也可能是异常信息  
private Object outcome; // non-volatile, protected by state reads/writes  
/** The thread running the callable; CASed during run() */  
private volatile Thread runner; // 任务执行线程  
/** Treiber stack of waiting threads */  
private volatile WaitNode waiters; // 等待线程的链表  
  
/**  
* 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);  
}  
  
/**  
* Creates a {@code FutureTask} that will, upon running, execute the  
* given {@code Callable}.  
*  
* @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.  
*  
* @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); // 创建一个callable对象  
this.state = NEW; // ensure visibility of callable  
}  
  
public boolean isCancelled() {  
return state >= CANCELLED;  
}  
  
public boolean isDone() {  
return state != NEW; // 不为NEW则代表已经完成  
}  
  
public boolean cancel(boolean mayInterruptIfRunning) {  
if (!(state == NEW && STATE.compareAndSet  
(this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))  
return false// 如果状态不是NEW 或者CAS修改状态失败则返回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(false0L);  
return report(s); // 获取结果 or 抛出异常  
}  
  
/**  
* 这个方法同 get() 就是加了测试  
*  
* @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)) { // run 方法执行完成后修改状态从NEW-> COMPLETING  
outcome = v;  
STATE.setRelease(this, NORMAL); // final state 如果设置成功状态后,将状态改为NORMAL  
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.  
*  
* <p>This method is invoked internally by the {@link #run} method  
* upon failure of the computation.  
*  
* @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() {  
// 校验当前任务状态,并且当前线程尝试获取执行权  
if (state != NEW ||  
!RUNNER.compareAndSet(thisnull, 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 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); // 处理方式:如果是中断中则一直释放自己的执行时间片,等待已中断  
}  
}  
  
/**  
* 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.  
*  
* @return {@code true} if successfully run and reset  
*/  
// 同run,只不过是在执行完成后不会设置返回值,而是返回任务状态与成功执行状态  
protected boolean runAndReset() {  
if (state != NEW ||  
!RUNNER.compareAndSet(thisnull, 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);  
}  
}  
} 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.  
*/  
// 如果状态为中断中, 则一直让出执行的CPU时间片,直到状态到已中断  
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)  
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();  
}  
  
/**  
* 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.  
*/  
private void finishCompletion() {  
// assert state > COMPLETING;  
for (WaitNode q; (q = waiters) != 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) { // > COMPLETING 代表线程已经由于一些情况结束了  
if (q != null)  
q.thread = null;  
return s;  
}  
else if (s == COMPLETING) // 如果完成则让出线程本次争用的CPU时间片  
// 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) // 如果未入队则放入队列头  
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  
// 阻塞线程等待唤醒,这里进入的条件是:  
// 1、线程状态为NEW  
// 2、线程未被中断  
// 3、线程未超时  
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) {  
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// 1、先判断当前节点是否是待删除节点  
pred = q; // 1.1、如果不是的话 pred 后移,直到找到待删除节点  
else if (pred != null) { // 2、如果找到了待删除节点【这里pred != null 判断了第一次进来的情况】  
pred.next = s; // 2.1、将待删除节点剔除。 就是很简单的链表后驱节点替换  
if (pred.thread == null// 如果发现前驱节点的线程为空,则代表前驱节点被其他线程置为待删除,这时重新执行retry循环,为了帮助剔除节点  
continue retry;  
}  
else if (!WAITERS.compareAndSet(this, q, s)) // 当要删除的是第一个waitNode 时,尝试将waitNode 后移。如果失败则代表已经有其他线程修改,则重新检查  
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.get()与线程池容易产生的问题?

/**
    如下代码,我们将线程池的拒绝策略设置为不作任何处理只打印一行日志,则会导致被拒绝线程的future.get() 一直卡主,因为通过report我们可知,future返回需要状态>COMPLETING,但是拒绝策略为抛出异常,没有产生修改futuretask状态的行为,故future.get() 会因为状态一直为NEW而无法返回,一直卡主。
*/
private static void runFutureTaskError() throws ExecutionException, InterruptedException {  
CountDownLatch latch = new CountDownLatch(1);  
ThreadPoolExecutor executor = new ThreadPoolExecutor(11,  
1, TimeUnit.SECONDS,  
new ArrayBlockingQueue<>(1),  
new ThreadFactory() {  
AtomicInteger count = new AtomicInteger(1);  
  
@Override  
public Thread newThread(Runnable r) {  
Thread newThread = new Thread(r);  
newThread.setDaemon(true);  
newThread.setPriority(Thread.NORM_PRIORITY);  
newThread.setName("future-task-" + count.getAndIncrement());  
return newThread;  
}  
},  
(r, e) -> {  
System.out.println("Task " + r.toString() +  
" rejected from " +  
e.toString());  
}  
);  
  
List<Future> futures = new ArrayList<>();  
  
futures.add(executor.submit(() -> {  
System.out.println("first thread");  
try {  
TimeUnit.SECONDS.sleep(5);  
} catch (InterruptedException e) {  
throw new RuntimeException(e);  
}  
System.out.println("first end.");  
}));  
  
futures.add(executor.submit(() -> {  
System.out.println("second thread");  
try {  
TimeUnit.SECONDS.sleep(1);  
} catch (InterruptedException e) {  
throw new RuntimeException(e);  
}  
System.out.println("second end.");  
}));  
  
futures.add(executor.submit(() -> {  
System.out.println("third thread");  
try {  
TimeUnit.SECONDS.sleep(1);  
} catch (InterruptedException e) {  
throw new RuntimeException(e);  
}  
System.out.println("third end.");  
}));  
  
for (Future future : futures) {  
future.get();  
}  
System.out.println("end");  
  
executor.shutdown();  
}