共同学习Java源代码-多线程与并发-FutureTask类(三)

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

    }

这个是静态终态内部类 将其他等待线程存储在这个链表结构的类里 


    private void finishCompletion() {
        // assert state > COMPLETING;
        for (WaitNode q; (q = waiters) != null;) {
            if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
                for (;;) {
                    Thread t = q.thread;
                    if (t != null) {
                        q.thread = null;
                        LockSupport.unpark(t);
                    }
                    WaitNode next = q.next;
                    if (next == null)
                        break;
                    q.next = null; // unlink to help gc
                    q = next;
                }
                break;
            }
        }


        done();


        callable = null;        // to reduce footprint
    }

这个方法是完成任务后的后续处理方法

先进入for循环遍历waitors 将waitors赋给循环变量q 

调用UNSAFE类的cas方法将waitors赋为空 如果这个方法返回true

再次进入一个内部for循环 

获取q也就是waitors 创建临时变量t 将q的thread属性赋给t

判断如果t不为空 也就是一个等待线程不为空 将q的thread属性置空 调用LockSupport的unpark方法 就是对线程进行解除阻塞 

然后判断如果q的下一个WaitNode为空就跳出内部for循环

将q的next属性置空 将q赋为下一个WaitNode节点 

最后跳出外部for循环

调用done方法这个模板方法 

最后将callable置空


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

这个方法是等待任务完成的方法

首先确定任务结束时间 判断第一个布尔值参数如果为true 截止日期就是当前日期加上第二个参数 否则就是0

创建WaitNode临时变量q赋为空 创建布尔值临时变量queued赋为false 

进入无限for循环

判断如果当前任务线程被打断 就调用removeWaitor方法删掉q 并抛出异常

然后判断状态不是NEW和COMPLETING 将q的thread属性置空 并返回状态

判断状态是COMPLETING 调用yield方法 让当前执行的线程变成就绪状态 

判断如果q为空 将q初始化为一个新的WaitNode

判断如果queued为false 调用UNSAFE的cas方法将q放在WaitNode链表第一位 代表不排队直接插队

判断如果timed为true 计算截止日期是否到了 如果到了 就调用removeWaiter方法 将q删除 并返回状态 如果时间没到 就调用LockSupport的parkNanos方法在剩余时间里阻塞本线程 

最后上述判断都不成立 就调用LockSupport的park方法阻塞住本线程


    private void removeWaiter(WaitNode node) {
        if (node != null) {
            node.thread = null;
            retry:
            for (;;) {          // restart on removeWaiter race
                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) // check for race
                            continue retry;
                    }
                    else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                          q, s))
                        continue retry;
                }
                break;
            }
        }
    }

这个是删除等待线程的方法

判断如果参数不为空 就将参数的thread属性置空 

进入名称为retry的无限for循环

进入内部for循环 循环变量pred为空 q赋为waiters s没有默认值 循环条件q不为空 一次循环结束后q赋为s

s赋为q的下一个节点 

判断如果q的thread属性不为空 将pred赋为q 

如果q的thread为空且pred不为空 pred的下一个节点赋为s 如果pred的thread属性为空 就continue名为retry的for循环

如果调用UNSAFE的cas方法将本对象的waiters设为s返回false的话 就continue名为retry的for循环

其实呢这个的原理就是 将参数节点的thread设为空 然后循环遍历时 将thread为空的节点删掉 内部循环结束了 就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);
        }
    }

这个是UNSAFE的相关属性 其实就是state runner waiters的属性的内存地址

FutureTask讲解完毕

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值