前面看过了很多利用AbstractQueuedSynchronizer做的二次开发,主要是针对锁的获取和释放以及状态的读取和变更做的一系列变化。
FutureTask和guava中的AbstractFuture很像,后者用一系列的set方法来设置值或异常来触发锁的释放。而FutureTask通过构造一个task任务,并用该任务的完成,用任务的返回值来设置future的value并触发锁的释放。
1.RunnableFuture
FutureTask实现了RunnableFuture接口,该接口组合了Runnable和Future两个接口,
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
在构造FutureTask的时候传入一个Callable,
public class FutureTask<V> implements RunnableFuture<V> {
/**
* Creates a <tt>FutureTask</tt> that will, upon running, execute the
* given <tt>Callable</tt>.
*
* @param callable the callable task
* @throws NullPointerException if callable is null
*/
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
sync = new Sync(callable);
}
...
}
实现Runnable接口的run方法,
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
public void run() {
sync.innerRun();
}
2.innerRun
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}
innerRun方法在FutureTask实现Runnable的run方法中执行,执行成功的话会把callable的返回值set到future的value中,如果抛出异常就设置异常,不管结果如何都会释放锁。
这里有double check,在原子设置状态从READY到RUNNING之后,还要在check一下现在的状态是否是RUNNING,防止调用了对外提供的public方法cancel,
public boolean cancel(boolean mayInterruptIfRunning) {
return sync.innerCancel(mayInterruptIfRunning);
}
boolean innerCancel(boolean mayInterruptIfRunning) {
for (;;) {
int s = getState();
if (ranOrCancelled(s))
return false;
if (compareAndSetState(s, CANCELLED))
break;
}
if (mayInterruptIfRunning) {
Thread r = runner;
if (r != null)
r.interrupt();
}
releaseShared(0);
done();
return true;
}
innerCancel方法会把正在运行的(状态是RUNNING)的task取消掉,所以要double check一下,如果被取消了,innerRun什么都不做,直接释放锁。
3.runAndReset可重用任务
/**
* 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 true if successfully run and reset
*/
protected boolean runAndReset() {
return sync.innerRunAndReset();
}
boolean innerRunAndReset() {
if (!compareAndSetState(READY, RUNNING))
return false;
try {
runner = Thread.currentThread();
if (getState() == RUNNING)
callable.call(); // don't set result
runner = null;
return compareAndSetState(RUNNING, READY);
} catch (Throwable ex) {
setException(ex);
return false;
}
}
这里如果调用reset方法,执行任务但不设置value,然后把所有状态reset到初始状态。
4.执行task的线程runner
每次释放锁的时候,都会把该runner置位null,在innerIsDone方法中同时通过state和runner的值来判断任务是否完成。/**
* Implements AQS base release to always signal after setting
* final done status by nulling runner thread.
*/
protected boolean tryReleaseShared(int ignore) {
runner = null;
return true;
}
boolean innerIsDone() {
return ranOrCancelled(getState()) && runner == null;
}
5.扩展FutureTask——ListenableFutureTask
增加了guava的ListenableFuture的addListener的属性。
通过覆写FutureTask提供的done()方法来完成附加的操作,比如这里执行添加的listener的操作。
/**
* Protected method invoked when this task transitions to state
* <tt>isDone</tt> (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() { }
/**
* Internal implementation detail used to invoke the listeners.
*/
@Override
protected void done() {
executionList.execute();
}
该done方法在通过set或者cancel方法成功,并释放了锁之后会调用。