LockSupport是什么?
“用于创建锁和其他同步类的基本线程阻塞原语。 ”,对于JDK官方文档上的介绍,听起来并不好懂。
是对线程唤醒机制Wait/Notify机制的改良版,提供Park()和unPark()两个方法来阻塞线程和解除阻塞。
Wait/Notify机制相对于LockSupport不好的地方?
Wait/Notify必须需要synchronized关键字加锁,才能使用,不然会有异常。
Wait/Notify必须先Wait,再Notify,顺序若相反,则阻塞不会被唤醒。
Conditional接口中Await/Signal机制相对于LockSupport不好的地方?
Await/Signal必须需要使用Lock加锁,才能使用,不然会有异常。
Await/Signal必须先Wait,再Notify,顺序若相反,则阻塞不会被唤醒。
LockSupport实践
LockSupport提供了“许可证”这样的概念来实现线程的阻塞与唤醒,许可证的取值是0或1.
LockSupport实现线程阻塞唤醒
public static void main(String[] args) {Thread threadA = new Thread(() -> {System.out.println("进入A线程");LockSupport.park();System.out.println("A线程被唤醒");});threadA.start();try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}// 由主线程唤醒A线程LockSupport.unpark(threadA);
}
LockSupport.unpark(Thread thread)方法解析
该方法主要用于派发许可证,内部主要使用UNSAFE类的uppark方法
public static void unpark(Thread thread) {if (thread != null)UNSAFE.unpark(thread);}
UNSAFE类的该方法是一个native方法
public native void unpark(Object var1);
LockSupport.park()方法解析
public static void park(Object blocker) {Thread t = Thread.currentThread();setBlocker(t, blocker);// 本质仍是调用UNSAFE类的park方法UNSAFE.park(false, 0L);setBlocker(t, null);}
如果先调用unpark(),就相当于已经发放了许可证,那么后调用park()将起作用,即不会阻塞。
应用实例
题目
实现一个容器,提供两个方法. add . size
写两个线程、线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线阳2给出提示并结束
public class MyTest {public static List<Integer> list = Collections.synchronizedList(new ArrayList<>());public static boolean flag = true;public static void add(int value){list.add(value);}public static Integer size(){return list.size();}public static void main(String[] args) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("添加元素"+i);add(i);if(i<=5){LockSupport.park();}}}});thread.start();new Thread(new Runnable() {@Overridepublic void run() {while(flag){if(size() == 5){flag = false;System.out.println("结束");}LockSupport.unpark(thread);}}}).start();}
}