011Java併發包011LockSupport
1 是什麼
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-----執行
4 總結
LockSuport是一個執行緒阻塞工具類,所有的方法都是靜態方法,可以讓執行緒在任意位置阻塞和喚醒。LockSupport底層呼叫的Unsafe中的native程式碼。
呼叫park()方法,如果憑證為1,則將憑證變成0,同時park()方法立即返回並繼續執行,如果憑證為0則會阻塞,直到unpark()方法執行將憑證從0變為1。
呼叫unpark()方法會將憑證從0變成1,多次呼叫unpark()的結果仍會使得憑證為1,不會導致憑證累加,憑證只有0和1兩種取值。