LockSupport是用来进行线程的通信的,是一个线程阻塞的工具类,其中里面的方法都是静态方法,park()和unpark()的作用分别是阻塞线程和唤醒线程。
方式一:使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程
方式二:使用JUC包中的Condition的await()方法让线程等待,使用signal()方法唤醒线程
方式三:LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程
方式一必须在同步代码块或者同步方法中成对使用,先wait后notify才能正常使用。
方式二必须先获取锁后才能使用,并且是先await后signal才能正常使用。
LockSupport类中使用了一种名为Permit(许可证)的概念来实现阻塞和唤醒线程的功能,而且许可证只能有一个,不能累加。
park:许可证默认没有所以会阻塞,等到发放许可才能唤醒。
unpark:发放许可证,自动唤醒等待的线程。
- public class LockSupportDemo {
-
- public static void main(String[] args) {
- Thread t1 = new Thread(() -> {
- System.out.println(Thread.currentThread().getName() + "\t -----------come in");
- LockSupport.park(); //阻塞
- System.out.println(Thread.currentThread().getName() + "\t ----------被唤醒");
- }, "t1");
- t1.start();
-
- try {
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- new Thread(() -> {
- LockSupport.unpark(t1);//发放许可
- System.out.println(Thread.currentThread().getName() + "\t ----------发出通知");
- }, "t2").start();
-
- }
- }
形象的理解:线程阻塞时需要消耗凭证,这个凭证最多只有一个,当调用park时,如果有许可,那么就直接消耗,继续向下进行,如果没有,则阻塞等待许可证的发放。当调用unpark时,发放一个许可证,多次调用不会累加。
因为unpark获得了一个凭证,之后再调用park方法,就可以名正言顺的凭证消费,故不会阻塞,先发放了凭证后续可以畅通无阻。
因为凭证的数量最大为1,而调用两次park方法却需要两个许可,证不够,所以会阻塞。