一、LockSupport
LockSupport是一个线程工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,也可以在任意位置唤醒。
它的内部其实两类主要的方法:park(停车阻塞线程)和unpark(启动唤醒指定线程)
下面的需求使用LockSupport可以方便的实现线程间的阻塞和唤醒。
/**
*
* 需求: 有两个线程A、B,A线程向一个集合里面依次添加元素"abc"字符串,一共添加十次,
* 当添加到第五次的时候,
* 希望B线程能够收到A线程的通知,然后B线程执行相关的业务操作。
*
* 基于LockSupport实现线程间的阻塞和唤醒(推荐)
* 优点: 灵活,不需要关注是等待线程先进行还是唤醒线程先运行
* 需要知道线程的名字
*/
public class LockSupportDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
// 实现线程B
final Thread threadB = new Thread(() -> {
if (list.size() != 5) {
LockSupport.park();
}
System.out.println("线程B收到通知,开始执行自己的业务...");
});
Thread threadA = new Thread(() -> {
for (int i = 1; i <= 10; i++){
list.add("abc");
System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
if (list.size() == 5)
//唤醒指定线程B
LockSupport.unpark(threadB);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
threadA.start();
threadB.start();
}
}
二、和wait/notify对比
(1)wait和notify都是Object中的方法,在调用这两个方法前必须先获得锁对象,但是park不需要获取某个对象的锁就可以锁住线程。
(2)notify只能随机选择一个线程唤醒,无法唤醒指定的线程,unpark却可以唤醒一个指定的线程。