• FutureTask源码阅读


    Future

    我们都知道Future这个接口是为了去除主线程的等待时间,以方便用等待时间处理其他复杂的业务逻辑

    这个接口总共只有5个方法,通过方法名就可以见名知意

    public interface Future<V> {
        boolean cancel(boolean mayInterruptIfRunning);
        boolean isCancelled();
        boolean isDone();
        V get() throws InterruptedException, ExecutionException;
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    FutureTast

    FutureTast实现了Future接口以及Callable接口

    这是它的几个状态,state就代表线程目前运行的状态,它下面的属性都有对应解释

        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;//线程执行异常exception
        private static final int CANCELLED    = 4;//线程取消
        private static final int INTERRUPTING = 5;//线程中断中
    	private static final int INTERRUPTED  = 6;//线程中断成功
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    适配器

    FutureTask可以传入一个runnable接口,因为它使用了适配器模式

    以下,通过构造方法传入runnable以及返回值

        public FutureTask(Runnable runnable, V result) {
            this.callable = Executors.callable(runnable, result);
            this.state = NEW;       // ensure visibility of callable
        }
    
    • 1
    • 2
    • 3
    • 4

    Executors的callable方法

        public static <T> Callable<T> callable(Runnable task, T result) {
            if (task == null)
                throw new NullPointerException();
            return new RunnableAdapter<T>(task, result);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    最终构造了适配器类,这个类继承了Callable,因此可以被看做是一个Callable,构造方法传入runnable以及结果,call则是执行方法

        static final class RunnableAdapter<T> implements Callable<T> {
            final Runnable task;
            final T result;
            RunnableAdapter(Runnable task, T result) {
                this.task = task;
                this.result = result;
            }
            public T call() {
                task.run();
                return result;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    run方法

        public void run() {
    		// compareAndSwapObject原子操作比较并交换两个值
            if (state != NEW ||
                !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                             null, Thread.currentThread()))
                return;
            // 满足条件后
            try {
                Callable<V> c = callable;
                // 判断c是否空指针以及再次判断state是不是新建
                if (c != null && state == NEW) {
                    V result;
                    // 标识是否执行成功
                    boolean ran;
                    try {
                    	// 尝试去执行自定义的call并且把ran标识为true
                        result = c.call();
                        ran = true;
                    } catch (Throwable ex) {
                    	// 失败了,将返回值设为null
                        result = null;
                        ran = false;
                        setException(ex);
                    }
                    // 如果执行成功,调用set方法
                    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);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    成功则调用set方法

         protected void set(V v) {
            // CAS切换到中间状态COMPLETING
            if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
                // 设置返回值
                outcome = v;
                // 设置为正常结束
                // 到达终态后不能再继续转换,因此可以使用lazySet
                UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
                // 唤醒执行期间因#get()阻塞的线程
                finishCompletion();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    get

    get方法用于获取结果,如果state的值不满足条件,会进入等待方法

    这里int s = state;语句用于获取当前值,state是可以被改变的

        public V get() throws InterruptedException, ExecutionException {
            int s = state;
            if (s <= COMPLETING)
                s = awaitDone(false, 0L);
            return report(s);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果s小于1会让这个线程等待结果

        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;
                }
                else if (s == COMPLETING) // cannot time out yet
                    Thread.yield();
                else if (q == null)
                    q = new WaitNode();
                else if (!queued)
                    queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                         q.next = waiters, q);
    			// 剩余时间
                else if (timed) {
                	// 计算需要等待的时间
                    nanos = deadline - System.nanoTime();
                    if (nanos <= 0L) {
                        removeWaiter(q);
                        return state;
                    }
                    LockSupport.parkNanos(this, nanos);
                }
                else
                    LockSupport.park(this);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    外包干了3个月,技术退步明显。。。。。
    C#面:解释什么是viewstate,能否禁用?是否所用控件都可以禁用
    WPF + Winform 解决管理员权限下无法拖放文件的问题
    7-90 螺旋方阵
    麻了,不要再动不动就BeanUtil.copyProperties!!!
    无需插数据线,adb通过wifi无线调试
    dubbo原理
    cobol基本语法
    51单片机学习:DS1302时钟实验
    数电第一次实验
  • 原文地址:https://blog.csdn.net/sekever/article/details/126021003