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的tryAcquireSharedtryReleaseShared方法。其中,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;
        }