LockSupport线程工具类解析
在以往的线程交互中,我们唤醒线程或者阻塞线程一般都是用notify/wait/await等等函数,但是还是不够灵活。例如说,我现在有十个线程,如果是我想唤醒或者挂起这其中的一部分线程的话,那我可以使用Condition,将这部分线程分队列,也就是ReentrantLock里面的,newCondition,但是此时我的需求是想要唤醒第七个线程,然后让第二个线程阻塞,那么不管是Condition还是wait,notify,都显得麻烦,力不从心,因此为了解决这个问题,就出现了这个线程工具类Locksupport
LockSupport概述
LockSupport是为了方便的对线程进行交互,而开发出来的线程工具类。基于UnSafe来实现的,最主要的作用是挂起和唤醒线程。
对于LockSupport来说,用的最多的以及最重要的方法,就是Park()系列方法和UnPark()系列方法了。
park方法
pack
方法 | 解释 |
---|---|
park(Object) | 挂起当前线程 |
parkNanos(Object,long) | 指定了一个挂起时间(相对于当前的时间),时间到后自动被唤醒;例如1000纳秒后自动唤醒 |
parkUntil(Object,long) | 指定一个挂起时间(绝对时间),时间到后自动被唤醒;例如2018-02-1221点整自动被唤醒。 |
park() | 和park(Object)相比少了挂起前为线程设置blocker、被唤醒后清理blocker的操作。 |
parkNanos(long) | 和parkNanos(Object,long)类似,仅少了blocker相关的操作 |
parkUntil(long) | 和parkUntil(Object,long)类似,仅少了blocker相关的操作 |
- park(Object) 源码
public static void park(Object blocker) {
//获取当前线程
Thread t = Thread.currentThread();
//设置线程parkBlocker
setBlocker(t, blocker);
//阻塞线程
UNSAFE.park(false, 0L);
//清除parkBlocker
setBlocker(t, null);
}
可以看到,park是默认阻塞的是当前的线程。举个代码的例子
public class LockSupportDemo1 {
public static void main(String[] args) {
System.out.println("开始");
LockSupport.park();
System.out.println("结束");
}
}
这个程序只会输出开始,而且一直都不会结束,因为主线程已经被阻塞了。但是没有其他的线程唤醒它,就会被一直阻塞住。在别的线程调用UnPark方法的时候,并且把当前线程作为参数时,那个因为调用了park方法而被阻塞的线程才会被唤醒
unPark方法
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
这个方法其实很简单,传入需要唤醒的线程的引用,然后就会唤醒那个线程。另外还有一个特点就是,当线程在调用park()之前调用了unPark,那么park方法也会被马上唤醒。像这样
public class LockSupportDemo1 {
public static void main(String[] args) {
System.out.println("开始");
LockSupport.unpark(Thread.currentThread());
LockSupport.park();
System.out.println("结束");
}
}
像这样,代码的输出仍然会是
开始
结束
应用代码示例
要求:两个线程交替输出1A2B......,思路,这个时候就可以用到LockSupport,当输出完一次之后,就休眠当前线程,唤醒另一个线程去输出
/**
* 两个线程交替输出1A2B......
*/
public class Test2 {
static Thread t1 = null;
static Thread t2 = null;
public static void main(String[] args) {
char[] num = "123456789".toCharArray();
char[] words = "ABCDEFGHI".toCharArray();
t1 = new Thread(() ->{
for (int i=0;i<num.length;i++){
System.out.println(num[i]);
LockSupport.park();
LockSupport.unpark(t2);
}
},"t1");
t2 = new Thread(() ->{
for (int i=0;i<words.length;i++){
System.out.println(words[i]);
LockSupport.unpark(t1);
LockSupport.park();
}
},"t2");
t1.start();
t2.start();
}
}