线程池(三)线程池执行FutureTask

251 阅读4分钟

线程池执行Callable任务

ThreadPoolExecutor的父类AbstractExecutorService中的submit()方法可以执行实现Callable接口的任务,同时可以在Future中获取任务的返回值。而实现Callable接口的任务是被包装成FutureTask任务来执行的。

// 执行Callable任务,可以获取任务返回值
public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}

// 将Callable任务包装成FutureTask任务
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

FutureTask结构

FutureTask实现了Runnable接口和Future接口,它可以由线程池的submit()方法执行,并且可以返回结果,而且任务本身也有不同的状态。

image.png

FutureTask的几种状态

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;  // 任务已被中断

FutureTask的字段和构造方法

// 保存FutureTask封装的Callable任务
private Callable<V> callable;

// 保存Callable当中call方法返回的结果
private Object outcome; 

// 正在执行call方法的线程
private volatile Thread runner;

// 保存被get方法挂起的线程,一个单向链表
private volatile WaitNode waiters;

static final class WaitNode {
    volatile Thread thread; // 被挂起的线程
    volatile WaitNode next; // 下一个节点
    WaitNode() { thread = Thread.currentThread(); }
}

// 构造方法
public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    // 任务初始为NEW状态
    this.state = NEW;
}

FutureTask执行任务

FutureTask实现了Runnable接口,而在submit()方法中任务被封装后是由execute()方法执行的,所以线程池最终执行的还是run()方法。

public void run() {
    // 1. 线程为初始状态,且可以成功设置当前执行run()方法的线程,则向下继续执行
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            // 2. 表示call()方法是否正常执行完成
            boolean ran;
            try {
                // 3. 任务正常执行完成 
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                // 4. 任务执行有异常
                result = null;
                ran = false;
                setException(ex);
            }
            // 5. 如果正常执行,则保存call()方法返回的结果
            if (ran)
                set(result);
        }
    } finally {
        // 置空当前执行run()方法的线程
        runner = null;
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

setException()方法保存任务执行过程中的异常,set()方法保存任务正常执行完之后的返回结果

protected void set(V v) {
    // 将New状态切换为Completing状态
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        // 保存结果到outcom中
        outcome = v;
        // 将状态设置为Normal状态
        UNSAFE.putOrderedInt(this, stateOffset, NORMAL);
        // 用于唤醒get方法中等阻塞的线程
        finishCompletion();
    }
}


protected void setException(Throwable t) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        // 将异常保存在返回结果中
        outcome = t;
        UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL);
        finishCompletion();
    }
}

finishCompletion()方法主要是唤醒waiters中被挂起的线程

private void finishCompletion() {
    // 1. 遍历所有被挂起的线程
    for (WaitNode q; (q = waiters) != null;) {
        // 2. 将挂在waiters置null,挂起的线程保留在q中
        if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
            for (;;) {
                Thread t = q.thread;
                if (t != null) {
                    q.thread = null;
                    // 3. 唤醒线程
                    LockSupport.unpark(t);
                }
                // 4. 获取下一个节点
                WaitNode next = q.next;
                if (next == null)
                    break;
                q.next = null;
                q = next;
            }
            break;
        }
    }

    done();

    callable = null;        // to reduce footprint
}

FutureTask获取结果

get()方法可以从任务返回的结果中阻塞获取结果,支持无限等待和有限等待两种方式

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);
}

awaitDone()可以将任务挂起,并将挂起的任务加到waiters中

private int awaitDone(boolean timed, long nanos)
    throws InterruptedException {
    // 1. timed表示是否超时阻塞,nanos表示阻塞时间
    final long deadline = timed ? System.nanoTime() + nanos : 0L;
    WaitNode q = null;
    boolean queued = false;
    // (1)任务中断抛出异常;(2)任务结束返回;(3)等待结束返回
    for (;;) {
        // 2. 如果线程被中断,则从等待队列中移除
        if (Thread.interrupted()) {
            removeWaiter(q);
            throw new InterruptedException();
        }

        // 3. 任务被执行完,绑定的thread置null(完成,异常,取消,异常)
        int s = state;
        if (s > COMPLETING) {
            if (q != null)
                q.thread = null;
            return s;
        }
        // 4. 任务正在执行,则让出CPU
        else if (s == COMPLETING)
            Thread.yield();
        // 5. 任务为新建,则创建新的WaitNode    
        else if (q == null)
            q = new WaitNode();
        // 6. WaitNode未入队列,则加入队列头部
        else if (!queued)
            queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                 q.next = waiters, q);
        else if (timed) {
            nanos = deadline - System.nanoTime();
            // 7. 如果等待结束,直接返回
            if (nanos <= 0L) {
                removeWaiter(q);
                return state;
            }
            // 8. 超时等待
            LockSupport.parkNanos(this, nanos);
        }
        else
            // 9. 无限等待
            LockSupport.park(this);
    }
}

report()方法返回任务的计算结果

private V report(int s) throws ExecutionException {
    // 返回outcome保存的结果
    Object x = outcome;
    if (s == NORMAL)
        return (V)x;
    if (s >= CANCELLED)
        throw new CancellationException();
    // 任务执行出现异常,返回任务的异常结果    
    throw new ExecutionException((Throwable)x);
}

FutureTask取消任务

cancel方法可以取消FutureTask的执行过程

// MayInterruptIfRunning表示可以在线程执行的时候中断
public boolean cancel(boolean mayInterruptIfRunning) {
    // 只有任务为NEW,且能将NEW状态变为中断或取消才会向下执行,否则返回false
    // 无法取消正在执行的任务
    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 {
                UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
            }
        }
    } finally {
        // 唤醒阻塞的线程
        finishCompletion();
    }
    return true;
}