在看AQS的时候发现它用到了LockSupport这个类,所以来瞄几眼~
AQS用它的代码场景:
private final booleanparkAndCheckInterrupt() {
LockSupport.park(this);
returnThread.interrupted();
}
调用了它的park()方法,我们一想嘛,就是将线程给暂停了,可是对于线程的暂停,我们都没细想,怎样才能去把一个线程暂停了?让它停在那里…..走进park()方法:
public static voidpark(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t,blocker);
UNSAFE.park(false,0L);
setBlocker(t, null);
}
首先,这个参数啊是一个Object,然后AQS调用它的时候传的是this,this就是AQS当前实例嘛,拿到这个实例做什么呢?
立马setBlocker(t, blocker)了一下,好,继续走进这个方法:
private static voidsetBlocker(Thread t,Object arg) {
// Even though volatile, hotspot doesn't need a write barrier here.
UNSAFE.putObject(t,parkBlockerOffset,arg);
}
可以看到,它调用了Unsafe的putObject方法,注意第二个参数parkBlockerOffset,它也是定义在LockSupport中的一个字段:
parkBlockerOffset=UNSAFE.objectFieldOffset(tk.getDeclaredField("parkBlocker"));
它存储的是parkBlocker这个字段在Thread对象实例中内存的偏移位置(不知道Thread里有哪些字段的自己去翻哈,友情提示我有写过Thread的文章~反正我只说parkBlocker字段在Thread中是用来存储当前是哪个对象暂停了线程),然后这个字段也就是仅仅通过LockSupport的getBlocker和setBlocker进行查询和修改。
那么我们就知道啦,setBlocker方法就干了一件事,就是把当前执行park方法这个对象赋给parkBlocker字段。这么做到底有何意义?因为我们看到,方法执行后下一句就是UNSAFE.park(false, 0L),再下一句setBlocker(t, null);又把这个字段赋值为null了!那么,是不是说明,这个字段在执行UNSAFE.park(false, 0L)这个方法时有用,那还等什么,让我们走进这个方法:
public native void park(boolean var1, long var2);
哎哟我去,就一句话,这个unsafe类里面的本地方法(没看过,不知道Unsafe是啥的请看我写的另一篇https://www.jianshu.com/p/558d323430eb)
好,那么它既然是个本地方法,我们就搜一下它是干嘛的嘛,嗖嗖嗖嗖,我发现了,它原来和Object.wait()差不多,一个功能,就是让线程停下来(sleep),等到unpark()被调用时再活过来,那,它和我们parkBlocker字段有什么关系??然后我继续搜了下,没发现什么关系,就是给一些调试工具调试打log用的,可以看到这个线程是因为啥停的,至于为啥要在UNSAFE.park()执行完就设为null, 我也不知道了~知道的朋友请告诉我呀~
Ok, 翻篇~所以呢LockSupport有个很重要的作用就是用来暂停和重新激活线程。阻塞也有不少方法可供选择:
public static void parkNanos(Object blocker, long nanos):sleep指定的时间
public static void parkUntil(Object blocker, long deadline):sleep直到某个特定时间
等等等等
需要注意,park()后此时线程是出于WAITING状态(不懂线程有哪些状态的自己去看昂!苦口婆心ing~)
所以综上,这个类还是十分简单滴,嗯,就酱~