1. 程式人生 > 實用技巧 >Java多執行緒——Semaphore&CyclicBarrier(訊號量與同步屏障)

Java多執行緒——Semaphore&CyclicBarrier(訊號量與同步屏障)

今天在leetcode刷了一道題,發現了新大陸,直呼妙啊!

以下為題目:

現在有兩種執行緒,氧 oxygen 和氫 hydrogen,你的目標是組織這兩種執行緒來產生水分子。

存在一個屏障(barrier)使得每個執行緒必須等候直到一個完整水分子能夠被產生出來。

氫和氧執行緒會被分別給予 releaseHydrogen 和 releaseOxygen 方法來允許它們突破屏障。

這些執行緒應該三三成組突破屏障並能立即組合產生一個水分子。

你必須保證產生一個水分子所需執行緒的結合必須發生在下一個水分子產生之前。

換句話說:

如果一個氧執行緒到達屏障時沒有氫執行緒到達,它必須等候直到兩個氫執行緒到達。
如果一個氫執行緒到達屏障時沒有其它執行緒到達,它必須等候直到一個氧執行緒和另一個氫執行緒到達。
書寫滿足這些限制條件的氫、氧執行緒同步程式碼。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/building-h2o
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

以下為題解:

 1 class H2O {
 2     private CyclicBarrier cyclicBarrier;
 3     private Semaphore hydrogen;
 4     private Semaphore oxygen;
 5     public H2O() {
 6         this.cyclicBarrier = new CyclicBarrier(3);
7 this.hydrogen = new Semaphore(2); 8 this.oxygen = new Semaphore(1); 9 } 10 11 public void hydrogen(Runnable releaseHydrogen) throws InterruptedException { 12 hydrogen.acquire(); 13 // releaseHydrogen.run() outputs "H". Do not change or remove this line. 14 releaseHydrogen.run();
15 try { 16 cyclicBarrier.await(); 17 hydrogen.release(); 18 } catch (BrokenBarrierException e) { 19 e.printStackTrace(); 20 } 21 } 22 23 public void oxygen(Runnable releaseOxygen) throws InterruptedException { 24 oxygen.acquire(); 25 // releaseOxygen.run() outputs "O". Do not change or remove this line. 26 releaseOxygen.run(); 27 try { 28 cyclicBarrier.await(); 29 oxygen.release(); 30 } catch (BrokenBarrierException e) { 31 e.printStackTrace(); 32 } 33 } 34 }

對於程式碼進行部分解釋:

Semaphore為訊號量,其acquire()方法為申請一個資源,使其在例項化時設定的最大資源數(初始訊號量)-1,而release方法為釋放一個資源使其+1;

CyclicBarrier為同步屏障,在JDK1.5被引入,可以讓一組執行緒達到一個屏障時被阻塞,直到最後一個執行緒達到屏障時,所以被阻塞的執行緒才能繼續執行。CyclicBarrier好比一扇門,預設情況下關閉狀態,堵住了執行緒執行的道路,直到所有執行緒都就位(執行到此行程式碼前),門才打開,讓所有執行緒一起通過。其例項化時的值可以理解為,屏障處多少個執行緒到達時放行。其await()方法則為插入屏障。

 初步瞭解後感嘆於巧妙!感受到了興奮與驚奇!!!(菜雞沒見過世面)