[JDK-JUC]-FutureTask

74 阅读4分钟

1. Runnable

只有一个run方法,用于异步执行。该方法的缺陷是没有返回值,任务提交后,提交线程不能跟进提交的任务的执行情况,例如是否执行完毕,是否执行成功...

void run()

2. Callable

这个接口的call()方法提供了返回值,而且抛出了异常,使得提交线程能够控制异步执行的提交任务。 V call() throws Exception

3. Future

我们说Callable可以控制异步提交的任务,具体如何控制,可以做哪些控制呢?答案就在Future接口中。 Future是Callable留给非执行线程的一个遥控器,使得用户可以跨线程的进行交互。

public interface Future<V> {  
    //取消任务
    boolean cancel(boolean mayInterruptIfRunning);
    //判断任务是否被取消
    boolean isCancelled();
    //判断任务是否执行完毕
    boolean isDone();  
    //获取任务执行结果
    V get();
    //带超时时间的get()方法
    V get(long timeout, TimeUnit unit);  
}

4. FutureTask

  package java.util.concurrent;  
import java.util.concurrent.locks.LockSupport;  
  
  
public class FutureTask<V> implements RunnableFuture<V> {  
  
//任务的当前状态,有7种状态  
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;  
  
//异步提交执行的任务  
private Callable<V> callable;  
  
//任务的执行结果:如果正常返回则是执行结果,如果出现异常,则为异常结果  
private Object outcome; // non-volatile, protected by state reads/writes  
  
//执行任务的线程  
private volatile Thread runner;  
  
//等待任务执行结果的线程(调用get()方法的线程)  
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);  
}  
  
/**  
* 构造函数,指定需要提交的任务  
* 任务不能为null  
* state初始化为NEW  
*/  
public FutureTask(Callable<V> callable) {  
if (callable == null)  
throw new NullPointerException();  
this.callable = callable;  
this.state = NEW;  
}  
  
/**  
* 构造函数,指定Runnable和结果,两者合并成callable  
* state初始化为NEW  
*/  
public FutureTask(Runnable runnable, V result) {  
this.callable = Executors.callable(runnable, result);  
this.state = NEW;  
}  
  
//如果状态>=CANCELLED(CANCELLED, INTERRUPTING, INTERRUPTED),则说明任务是取消的  
public boolean isCancelled() {  
return state >= CANCELLED;  
}  
  
//只要状态不是NEW,就说明任务已经完成  
public boolean isDone() {  
return state != NEW;  
}  
  
/**  
* 取消任务  
* 1. 如果state != NEW,不能执行cancel操作,直接返回false  
* 2. 将state状态改成INTERRUPTING或CANCELLED,更改失败,直接返回false  
* 3. 如果可中断线程,则获取到任务的执行线程,执行中断操作,并将state更改为INTERRUPTED  
* 4. 调用waiters线程的LockSupport.unpark(t)方法  
*/  
public boolean cancel(boolean mayInterruptIfRunning) {  
//如果任务没有完成(isDone()),或者更新state失败,那么直接返回false  
//也就是说,只有state为NEW时,才能执行cancel操作  
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 { // final state  
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);  
}  
}  
} finally {  
finishCompletion();  
}  
return true;  
}  
  
/**  
* 获取任务执行结果  
*/  
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;  
if (s <= COMPLETING &&  
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)  
throw new TimeoutException();  
return report(s);  
}  
  
protected void done() { }  
  
  
protected void set(V v) {  
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {  
outcome = v;  
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state  
finishCompletion();  
}  
}  
  
  
protected void setException(Throwable t) {  
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {  
outcome = t;  
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state  
finishCompletion();  
}  
}  
  
public void run() {  
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 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  
*/  
protected boolean runAndReset() {  
if (state != NEW ||  
!UNSAFE.compareAndSwapObject(this, runnerOffset,  
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);  
}  
}  
} 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.  
*/  
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  
  
}  
  
/**  
* 等待结果的线程链表  
*/  
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 (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  
}  
  
/**  
* 阻塞等待  
*/  
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)  
q = new WaitNode();  
else if (!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);  
}  
}  
  
/**  
* 删除等待线程  
*/  
private void removeWaiter(WaitNode node) {  
if (node != null) {  
node.thread = null;  
retry:  
for (;;) {  
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;  
}  
}  
}  
  
// 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);  
}  
}  
  
}