通过Future和Callable可以实现异步计算框架,实现流程如下:
1、实现Callable接口里的call方法。2、FutureTask(Callable<V> callable)new FutureTask 3、Thread(FutureTask ).start启动线程4、FutureTask的get()方法阻塞式得到结果。
二、源码分析
//通过下面可以看到:FutureTask实现了Runnable接口和Future接口,所有可以和Runnable接口一样被Thread进行启动。(其实Thread也实现了Runnable接口)
public class FutureTask<V> implements RunnableFuture<V> {
public interface RunnableFuture<V> extends Runnable, Future<V> {
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
sync = new Sync(callable);//Sync为继承的AQS队列
}
public void run() {//通过FutureTask的run包装了Callable里的call方法的执行,start启动调用该方法
sync.innerRun();
}
public V get() throws InterruptedException, ExecutionException {
return sync.innerGet();
}
public boolean cancel(boolean mayInterruptIfRunning) {
return sync.innerCancel(mayInterruptIfRunning);
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------
private final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -7828117401763700385L;
/** State value representing that task is running */
private static final int RUNNING = 1;
/** State value representing that task ran */
private static final int RAN = 2;
/** State value representing that task was cancelled */
private static final int CANCELLED = 4;
/** The underlying callable */
private final Callable<V> callable;
/** The result to return from get() */
private V result;
/** The exception to throw from get() */
private Throwable exception;
/**
* The thread running task. When nulled after set/cancel, this
* indicates that the results are accessible. Must be
* volatile, to ensure visibility upon completion.必须是volatile确保线程完成后的可见性
*/
private volatile Thread runner;
void innerRun() {
if (!compareAndSetState(0, RUNNING))
return;
try {
runner = Thread.currentThread();
if (getState() == RUNNING) // recheck after setting thread因为没有加锁进行多次检查
innerSet(callable.call());//调用call方法完成执行任务
else
releaseShared(0); // cancel
} catch (Throwable ex) {
innerSetException(ex);
}
}
void innerSet(V v) {
for (;;) {
int s = getState();
if (s == RAN)
return;
if (s == CANCELLED) {
// aggressively release to set runner to null,
// in case we are racing with a cancel request
// that will try to interrupt runner
releaseShared(0);//直接唤醒阻塞等待获取结果的线程队列
return;
}
if (compareAndSetState(s, RAN)) {//修改为执行完成状态
result = v;//赋值任务结果,普通私有变量,如何确保其他线程的可见性?
releaseShared(0);//其中会涉及到volatile runner变量的写入,确保了result的结果借助 volatile的写同步到主内存
done();
return;
}
}
}
protected int tryAcquireShared(int ignore) {
return innerIsDone()? 1 : -1;//在RAN | CANCELLED状态返回1,进入到唤醒阻塞的结果线程队列
}
boolean innerIsDone() {
return ranOrCancelled(getState()) && runner == null;
}
private boolean ranOrCancelled(int state) {
return (state & (RAN | CANCELLED)) != 0;
}
protected boolean tryReleaseShared(int ignore) {
runner = null;//其中会涉及到volatile runner变量的写入
return true;
}
总结:Future表示任务的所有操作将在Future.get中返回之前执行。run方法通过对volite变量的写入确保之前的结果result写入都存储会主内存,通过在get方法里对volatile state变量的读取,确保了线程工作内存加载了最新的主内存信息。使result得以在不同的线程之间进行传递