共同学习Java源代码-多线程与并发-FutureTask类(三)
来源:互联网 发布:js中数组 编辑:程序博客网 时间:2024/06/10 01:34
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讲解完毕
- 共同学习Java源代码-多线程与并发-FutureTask类(三)
- 共同学习Java源代码-多线程与并发-FutureTask类(一)
- 共同学习Java源代码-多线程与并发-FutureTask类(二)
- 共同学习Java源代码-多线程与并发-AbstractExecutorService类(三)
- 共同学习Java源代码-多线程与并发-ThreadPoolExecutor类(三)
- 共同学习Java源代码-多线程与并发-AbstractExecutorService类(一)
- 共同学习Java源代码-多线程与并发-AbstractExecutorService类(二)
- 共同学习Java源代码-多线程与并发-ThreadPoolExecutor类(一)
- 共同学习Java源代码-多线程与并发-ThreadPoolExecutor类(二)
- 共同学习Java源代码-多线程与并发-ThreadPoolExecutor类(四)
- 共同学习Java源代码-多线程与并发-Executor、ExecutorService接口
- 共同学习Java源代码-多线程与并发-Future、RunnableFuture接口
- 共同学习Java源代码-多线程与并发-BlockingQueue接口
- 共同学习Java源代码-多线程与并发-CompletionService接口和ExecutorCompletionService类
- 共同学习Java源代码--常用工具类--AbstractStringBuilder(三)
- 共同学习Java源代码--常用工具类--StringBuffer(三)
- 共同学习Java源代码--数据结构--AbstractList抽象类(三)
- 共同学习Java源代码--数据结构--ArrayList类(三)
- Tree Longest Path With Same Value -LintCode
- 关于网页显示的问题
- 解析Linux操作系统文件目录
- C++的std::to_string():数值转换字符串
- 多线程共同使用一个锁引发的死锁问题
- 共同学习Java源代码-多线程与并发-FutureTask类(三)
- javvascript的map函数与each函数的区别
- 新安装Visio2013每次打开都提示正在配置,解决办法
- Android把延时器封装成全局方法——适合菜鸟使用
- 游戏开发学习笔记(十)购买物品
- NOIP2017游记
- 【Unity】5.6版本无法新建工程解决办法
- 日常3.0--关于linux的操作记录(CentOS-JDK)
- cpu之Data_memory