Java FutureTask 源码解析
简介
Java中的FutureTask类是一个可取消的异步计算任务,它实现了Future接口和Runnable接口,可以在多线程环境下使用。FutureTask类提供了所需计算的结果获取方法,以及取消任务的方法。
使用示例
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class FutureTaskExample {
public static void main(String[] args) {
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
// 计算任务,这里假设计算结果为100
return 100;
}
};
FutureTask<Integer> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
try {
// 获取计算结果
int result = futureTask.get();
System.out.println("计算结果:" + result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
上面的示例中,我们创建了一个Callable对象,并将其作为参数传递给FutureTask的构造函数。然后我们创建了一个线程,启动线程后调用futureTask.get()
方法获取计算结果。
FutureTask 源码解析
构造函数
FutureTask类有多个构造函数,我们使用的是以下构造函数:
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
sync = new Sync(callable);
}
构造函数会将传入的Callable对象封装到一个Sync对象中。
Sync类
Sync类是FutureTask的内部类,它继承了AQS(AbstractQueuedSynchronizer)类。AQS是一个用于构建锁和同步器的基础框架。
Sync类中有一个state
变量和一个callable
变量,分别用于保存任务状态和Callable对象。
Sync类实现了AQS的tryAcquireShared
和tryReleaseShared
方法。其中,tryAcquireShared
方法用于获取共享锁,tryReleaseShared
方法用于释放共享锁。
run方法
FutureTask类实现了Runnable接口,因此它可以作为一个线程任务执行。当我们创建一个线程并启动它时,线程会调用FutureTask的run方法。
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);
}
}
在run方法中,首先判断任务的状态是否为NEW,如果不是,说明任务已经被执行过了,直接返回。如果任务的状态为NEW,说明任务尚未执行,调用Callable对象的call方法执行任务,并将返回结果保存起来。
在执行过程中,如果有异常产生,通过setException
方法将异常信息保存起来。
如果任务成功执行完毕,通过set
方法将结果保存起来。
最后,将runner
变量置为null,表示任务已经执行完毕。
get方法
FutureTask类提供了多个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);
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}