手撕FutureTask源码解读

Runnable不是线程,只是线程的入口,Thread中有Runnable属性,Runnable调用run()方法,去执行Runnable target

public class FutureTask<V> implements RunnableFuture<V> {
    //表示当前task状态
    private volatile int state;
    //当前任务尚未执行
    private static final int NEW          = 0;
    //当前任务正在结束,尚未完全结束,一种临界状态
    private static final int COMPLETING   = 1;
    //当前任务正常结束
    private static final int NORMAL       = 2;
    //当前任务执行过程中发生了异常,内部封装的Callable.run()向上抛出异常
    private static final int EXCEPTIONAL  = 3;
    //当前任务被取消
    private static final int CANCELLED    = 4;
    //当前任务中断中
    private static final int INTERRUPTING = 5;
    //当前任务已中断
    private static final int INTERRUPTED  = 6;

    //submit(runnable/callable) runnable使用装饰者模式伪装成Callable了。
    private Callable<V> callable;
    //正常情况:任务正常结束,outcome保存执行结果,callable返回值.
    //非正常情况下:callable向上抛出异常。outcome保存异常.
    private Object outcome;
    //当前任务被线程执行期间,保存当前执行任务的线程对象引用.
    private volatile Thread runner;
    //因为会有很多线程get当前任务的结果,所以这里使用了一种数据结构 stack 头插 头取 的一个队列.
    private volatile WaitNode waiters;


    private V report(int s) throws ExecutionException {
        //正常情况下:outcome保存的是callable运行结束的结果.
        //非正常,保存的是callable抛出的异常
        Object x = outcome;
        //条件成立:当前任务状态正常结束
        if (s == NORMAL)
            //直接返回callable运算结果
            return (V)x;
        //被取消状态
        if (s >= CANCELLED)
            throw new CancellationException();
        //执行到这里,说明callable接口实现中,是有bug了
        throw new ExecutionException((Throwable)x);
    }

    /**
     * 构造方法
     * @param callable
     */
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        //callable就是程序员自己实现的业务类
        this.callable = callable;
        //设置当前状态为 NEW
        this.state = NEW;
    }

    /**
     * 构造方法
     * @param runnable
     * @param result
     */
    public FutureTask(Runnable runnable, V result) {
        //使用装饰者模式将Runnable转换为了callable接口,外部线程通过get获取
        //当前任务执行结果时,结果可能为null,也可能为传进来的值.
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;
    }

    public boolean isCancelled() {
        return state >= CANCELLED;
    }

    public boolean isDone() {
        return state != NEW;
    }

    public boolean cancel(boolean mayInterruptIfRunning) {
        //条件一:state == NEW 成立,表示当前任务处于运行中 或者 处于线程池任务队列中..
        //条件二:UNSAFE.compareAndSwapInt(this, stateOffset, NEW,mayInterruptIfRunning ? INTERRUPTING : CANCELLED)
        //      条件成立,说明状态修改成功,可以执行下面的逻辑,否则,返回false 表示cancel失败
        if (!(state == NEW &&
                UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
                        mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
            return false;
        try {    // in case call to interrupt throws exception
            if (mayInterruptIfRunning) {
                try {
                    //执行当前FureTask的线程,有可能现在是null,shinull的情况:当前任务在队列中,还没有线程获取到它呢...
                    Thread t = runner;
                    //条件成立:说明当前线程runner,正在执行task
                    if (t != null)
                        //给runner线程一个中断信号.. 如果你的程序是响应中断的 会走中断逻辑..假设你的程序不是响应中断的..
                        //啥也不会发生
                        t.interrupt();
                } finally { // final state
                    //设置任务状态为 中断完成
                    UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
                }
            }
        } finally {
            //唤醒所有get() 阻断的线程
            finishCompletion();
        }
        return true;
    }

   //场景:多个线程等待当前任务执行完成后的结果.....
    public V get() throws InterruptedException, ExecutionException {
        //获取当前任务状态
        int s = state;
        //条件成立,执行、正在执行、正完成。调用get外部线程会被阻塞在get方法上。
        if (s <= COMPLETING)
            //核心地方:阻塞线程
            //返回task当前状态,可能当前线程在里面已经睡了一会.
            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);
    }


    protected void done() { }


    protected void set(V v) {
        //使用CAS方式设置当前任务状态为完成中.....
        //有没有可能失败呢?外部线程等不及了,直接在set执行CAS之前将task取消了.--小概率事件
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            //将结果赋值给outcome之后,马上会将当前任务状态修改为NORMAL正常结束状态.
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL);
            //结束执行
            //最起码要把get() 在此阻塞的线程唤醒..
            finishCompletion();
        }
    }

    protected void setException(Throwable t) {
        //使用CAS方式设置当前任务状态为完成中.....
        //有没有可能失败呢?外部线程等不及了,直接在set执行CAS之前将task取消了.--小概率事件
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            //引用的是callable向上层抛出来的异常.
            outcome = t;
            //将当前任务的状态修改为EXCEPTIONAL
            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL);
            //
            finishCompletion();
        }
    }



    public void run() {
        //条件一:state != NEW  条件成立,说明当前的task已经被执行过了 或者 被cancel了,总之非NEW状态的任务,线程就不处理了.
        //条件二: UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))
        //       条件成立,cas失败,当前任务被其他线程抢占了.....
        if (state != NEW ||
                !UNSAFE.compareAndSwapObject(this, runnerOffset,
                        null, Thread.currentThread()))
            return;
        //执行到这里,当前task一定是NEW状态,而且 当前线程也抢占task成功
        try {
            //callable就是程序员自己封装逻辑的callable或者是装饰后的runnable
            Callable<V> c = callable;
            //条件一: c != null 防止空指针异常
            //条件二: state==NEW 防止外部线程cancel掉当前任务.
            if (c != null && state == NEW) {
                //结果引用
                V result;
                //true 表示callable.run代码块执行成功,未抛出异常
                //false 表示callable.run代码块执行失败,抛出异常
                boolean ran;
                try {
                    //调用程序员自己实现的callable 或者 是装饰后的runnable
                    result = c.call();
                    //c.call()未抛出任何异常,ran会设置成true 代码块执行成功
                    ran = true;
                } catch (Throwable ex) {
                    //说明程序员自己写的逻辑块有bug了
                    result = null;
                    ran = false;
                    setException(ex);
                }
                //
                if (ran)
                    //说明当前c.call正常执行结束了
                    //set就是设置结果到outcome
                    set(result);
            }
        } finally {

            runner = null;
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }
    protected boolean runAndReset() {
        if (state != NEW ||
                !UNSAFE.compareAndSwapObject(this, runnerOffset,
                        null, Thread.currentThread()))
            return false;
        boolean ran = false;
        int s = state;
        try {
            Callable<V> c = callable;
            if (c != null && s == NEW) {
                try {
                    c.call(); // don't set result
                    ran = true;
                } catch (Throwable ex) {
                    setException(ex);
                }
            }
        } finally {
            runner = null;
            s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
        return ran && s == NEW;
    }

    private void handlePossibleCancellationInterrupt(int s) {
        if (s == INTERRUPTING)
            while (state == INTERRUPTING)
                Thread.yield();

    }


    static final class WaitNode {
        volatile Thread thread;
        volatile WaitNode next;
        WaitNode() { thread = Thread.currentThread(); }
    }

    private void finishCompletion() {
        // assert state > COMPLETING;
        //q指向waiters链表头节点
        for (WaitNode q; (q = waiters) != null;) {
            //使用cas设置waiter为null 是因为怕 外部线程使用 cancal取消当前任务,也会触发finishCompletion方法.小概率事件
            if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
                for (;;) {
                    //获取当前node节点封装的线程  thread
                    Thread t = q.thread;
                    //条件成立:说明当前线程不为null
                    if (t != null) {
                        q.thread = null; //helpGC
                        //唤醒当前节点对应的线程
                        LockSupport.unpark(t);
                    }
                    //next 当前节点的下一个节点
                    WaitNode next = q.next;

                    if (next == null)
                        break;
                    q.next = null;//helpGC
                    q = next;
                }
                break;
            }
        }

        done();
        //将callable设置为空
        callable = null;//helpGC
    }

    private int awaitDone(boolean timed, long nanos)
            throws InterruptedException {
        //0 不带超时的
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        //引用当前线程 封装成WaitNode对象
        WaitNode q = null;
        //表示当前线程WaitNode对象 有没有入队或者压栈
        boolean queued = false;
        for (;;) {
            //条件成立:说明当前线程唤醒,是被其他线程适应中断这种方式唤醒的。interrupted()返回true后会将Thread的中断标记重置回false
            if (Thread.interrupted()) {
                //当前线程node出队
                removeWaiter(q);
                //get方法抛出中断异常.
                throw new InterruptedException();
            }
            //假设当前线程是被其他的线程 使用unpark(thread)唤醒的话,会正常自旋,走下面的逻辑.
            //获取当前任务最新的状态
            int s = state;
            //条件成立:说明当前任务,已经有结果了..可能是好  可能是坏...
            if (s > COMPLETING) {
                //q条件成立:说明已经为当前线程创建过node了,此时需要将node.thread=null helpGC
                if (q != null)
                    q.thread = null;
                //直接返回当前状态.
                return s;
            }
            //条件成立:说明当前任务接近完成状态... 这里让当前线程再释放cpu.进行下一次抢占cpu
            else if (s == COMPLETING)
                Thread.yield();
            //条件成立:第一次自旋,当前线程还没有创建WaitNode对象,此时为当前线程创建WaitNode对象
            else if (q == null)
                q = new WaitNode();
            //条件成立:第二次自旋,当前线程已经创建WaitNode对象,但是WaitNode对象还没有入队
            else if (!queued)
                //将当前对象node节点,next指向原队列的头节点  waiters一直指向队列的头
                q.next = waiters;
                //CAS方式waiters引用指向当前线程node,成功的话,queued==true 否则,可能其他线程先你一步入队了.
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,  waiters, q);
             //第三次自旋回来到这里
            else if (timed) {
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                LockSupport.parkNanos(this, nanos);
            }
            else
                //当前get操作的线程就会park了,线程状态会变为WAITING状态相当于休眠了
                //除非有其他线程将你唤醒 或者 将当前线程中断
                LockSupport.park(this);
        }
    }

    //出队方法
    private void removeWaiter(WaitNode node) {
        if (node != null) {
            node.thread = null;
            retry: //自旋
            for (;;) {
                //遍历队列中的所有节点
                for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
                    s = q.next;
                    if (q.thread != null)
                        pred = q;
                    else if (pred != null) {
                        pred.next = s;
                        if (pred.thread == null)
                            continue retry;
                    }
                    //当前节点是头节点的情况
                    else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
                            q, s))
                        continue retry;
                }
                break;
            }
        }
    }

    private static final sun.misc.Unsafe UNSAFE;
    private static final long stateOffset;
    private static final long runnerOffset;
    private static final long waitersOffset;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> k = FutureTask.class;
            stateOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("state"));
            runnerOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("runner"));
            waitersOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("waiters"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值