08 多线程与高并发 - FutureTask 源码解析

FutureTask 介绍

可取消的同步非阻塞执行的任务。当任务执行完毕时,可获取返回结果。
FutureTask 除了实现了 Future 接口以外,还实现了 Runnable 接口,因此 FutureTask 可以用线程调用执行,也可以交由 Executor 执行。

  • 当 FutureTask 处于未启动或者已启动的状态时,调用 FutureTask 对象的 get 方法会将导致调用线程阻塞。
  • 当 FutureTask 处于已完成的状态时,调用 FutureTask 的 get 方法会立即返回调用结果或者抛出异常。

FutureTask 基本使用

FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            return 1+1;
        });
Thread t = new Thread(futureTask);
t.start();
Integer result = futureTask.get();
System.out.println(result);

FutureTask 源码分析

核心属性

/**
 * NEW -> COMPLETING -> NORMAL          任务正常执行,返回结果是正常的结果
 * NEW -> COMPLETING -> EXCEPTIONAL     任务正常执行,但是返回结果是异常
 * NEW -> CANCELLED                     任务直接被取消的流程
 * NEW -> INTERRUPTING -> INTERRUPTED
 */
// 代表当前任务的状态
private volatile int state;
private static final int NEW          = 0;  // 任务的初始化状态
private static final int COMPLETING   = 1;  // Callable的结果(正常结果,异常结果)正在封装给当前的FutureTask
private static final int NORMAL       = 2;  // NORMAL任务正常结束

private static final int EXCEPTIONAL  = 3;  // 执行任务时,发生了异常
private static final int CANCELLED    = 4;  // 任务被取消了。

private static final int INTERRUPTING = 5;  // 线程的中断状态,被设置为了true(现在还在运行)
private static final int INTERRUPTED  = 6;  // 线程被中断了。

// 当前要执行的任务
private Callable<V> callable;
// 存放任务返回结果的属性,也就是futureTask.get需要获取的结果
private Object outcome; 
// 执行任务的线程。
private volatile Thread runner;
// 单向链表,存放通过get方法挂起等待的线程
private volatile WaitNode waiters;

run()

public void run() {
		// 状态 == NEW && 将当前线程设置为 runner
        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 {
					// 执行call()
                    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);
        }
    }
set()
protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            // 任务执行完毕后唤醒线程
            finishCompletion();
        }
    }
setException()
protected void setException(Throwable t) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = t;
            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
            // 任务执行完毕后唤醒线程
            finishCompletion();
        }
    }

get()

public V get() throws InterruptedException, ExecutionException {
        int s = state;
        // 任务还未执行完
        if (s <= COMPLETING)
        // 尝试挂起线程,头插法插入 waiters 中
            s = awaitDone(false, 0L);
        // 包装结果返回
        return report(s);
    }
awaitDone()

尝试挂起线程,将当前节点头插法插入 waiters 中

private int awaitDone(boolean timed, long nanos) throws InterruptedException {
		// 超时时间
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
			//1. 中断标识,从waiters中移除当前节点
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }
			
            int s = state;
			//2. 任务结束,返回状态值
            if (s > COMPLETING) {
                if (q != null)
                    q.thread = null;
                return s;
            }
			//3. 正在封装当前的返回结果,让出cpu一下
            else if (s == COMPLETING) // cannot time out yet
                Thread.yield();
			//4. 封装 WaitNode(到这,根据上面的条件此时state只可能是NEW)
            else if (q == null)
                q = new WaitNode();
			//5. 头插法将WaitNode加入waiters
            else if (!queued)
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                     q.next = waiters, q);
			//6. 指定时间挂起线程
            else if (timed) {
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                LockSupport.parkNanos(this, nanos);
            }
			//7. 挂起线程
            else
                LockSupport.park(this);
        }
    }
report()

包装结果返回

private V report(int s) throws ExecutionException {
        Object x = outcome;
		// 正常返回
        if (s == NORMAL)
            return (V)x;
		// 任务状态大于取消,抛异常
        if (s >= CANCELLED)
            throw new CancellationException();
		// s == EXCEPTIONAL
        throw new ExecutionException((Throwable)x);
    }

finishCompletion()

任务执行完毕后唤醒线程,在set(),setException(),cancel() 中进行调用

// 任务状态已经变为了NORMAL,做一些后续处理
private void finishCompletion() {
    for (WaitNode q; (q = waiters) != null;) {
        // 拿到第一个节点后,直接用CAS的方式,将其设置为null
        if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
            for (;;) {
                // 基于q拿到线程信息
                Thread t = q.thread;
                // 线程不为null
                if (t != null) {
                    // 将WaitNode的thread设置为null
                    q.thread = null;
                    // 唤醒这个线程
                    LockSupport.unpark(t);
                }
                // 往后遍历,接着唤醒
                WaitNode next = q.next;
                if (next == null)
                    break;
                q.next = null;
                // 指向next的WaitNode
                q = next;
            }
            break;
        }
    }
    // 扩展方法,没任何实现,你可以自己实现
    done();
    // 任务处理完了
    callable = null;   
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小刘说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值