LockSupport是用来创建锁和其他同步类的基本线程阻塞原语,在内部使用一个许可证的概念来实现阻塞和唤醒,每个线程都有一个许可证,许可证只有1和0两个值,默认是0。
LockSupport中的park()和unpark()的作用分别是阻塞线程和解除阻塞线程,park()方法会在许可证可用时执行,unpark()方法会在许可证不可用时提供许可证。
归根结底,LockSupport调用的Unsafe中的native代码。
2 比较1)使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程。
必须在synchronized内部执行,否则抛出IllegalMonitorStateException。
必须先执行wait()方法再执行notify()方法,即只能在wait()方法后使用notify()方法唤醒,否则程序将一直等待无法被唤醒。
2)使用Condition的await()方法让线程等待,使用Condition的signal()方法唤醒线程。
必须和Lock组队使用,否则抛出IllegalMonitorStateException。
只能在wait()方法后使用notify()方法唤醒,否则程序将一直等待无法被唤醒。
3)使用LockSupport的park()方法让线程等待,使用LockSupport的uppark()方法唤醒线程。
不需要在任何方法块内执行,park()方法和uppark()方法都是静态方法,可以在任何地方执行。
使用顺序无要求,即便uppark()方法提前,也能保证park()方法被唤醒。
3 使用代码如下:
1 public static void main(String[] args) { 2 Thread a = new Thread(()->{ 3 try { 4 Thread.sleep(3000); 5 } catch (InterruptedException e) { 6 e.printStackTrace(); 7 } 8 System.out.println(Thread.currentThread().getName() + "-----进入"); 9 LockSupport.park(); 10 System.out.println(Thread.currentThread().getName() + "-----执行"); 11 }, "a"); 12 a.start(); 13 Thread b = new Thread(()->{ 14 System.out.println(Thread.currentThread().getName() + "-----进入"); 15 LockSupport.unpark(a); 16 System.out.println(Thread.currentThread().getName() + "-----执行"); 17 }, "b"); 18 b.start(); 19 }
结果如下:
1 b-----进入 2 b-----执行 3 // 等待三秒 4 a-----进入 5 a-----执行
LockSuport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞和唤醒。LockSupport底层调用的Unsafe中的native代码。
调用park()方法,如果凭证为1,则将凭证变成0,同时park()方法立即返回并继续执行,如果凭证为0则会阻塞,直到unpark()方法执行将凭证从0变为1。
调用unpark()方法会将凭证从0变成1,多次调用unpark()的结果仍会使得凭证为1,不会导致凭证累加,凭证只有0和1两种取值。