Java 并發專題 : CyclicBarrier 打造一個安全的門禁系統
繼續并發專題~
這次介紹CyclicBarrier:看一眼API的注釋:
/** * A synchronization aid that allows a set of threads to all wait for * each other to reach a common barrier point. CyclicBarriers are * useful in programs involving a fixed sized party of threads that * must occasionally wait for each other. The barrier is called * <em>cyclic</em> because it can be re-used after the waiting threads * are released.
大概意思:一個讓一組線程同時阻塞到一個位置的同步輔助類。在包含固定線程且線程間必須相互等待的場景中非常有用。cyclic的意思是CyclicBarrier當等待的線程全部釋放之后,可以重復使用。(英語水平就這樣了。。。。)
CyclicBarrier 類似一個閘門,指定數目的線程都必須到達這個閘門,閘門才會打開。
下面使用CyclicBarrier模擬一個門禁系統:
需求是這樣的:到放學時間,所有的學生必須刷卡,然后人數齊了自動開門,統一回家。這個需求剛剛的,避免了把部分孩子丟在學校發生危險,特別是幼兒園或者小學生~~
package com.zhy.concurrency.cyclic; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * 安全的門禁系統 * * @author zhy * */ public class CyclicBarrierTest { /** * 學生總數 */ private final int STUDENT_COUNT = 10; /** * 當人到齊,自動開門程序 */ final CyclicBarrier barrier = new CyclicBarrier(STUDENT_COUNT, new Runnable() { @Override public void run() { System.out.println("人到齊了,開門...."); } }); public void goHome() throws InterruptedException, BrokenBarrierException { System.out.println(Thread.currentThread().getName() + "已刷卡,等待開門回家~"); barrier.await(); System.out.println(Thread.currentThread().getName() + "放學回家~"); } public static void main(String[] args) throws InterruptedException, BrokenBarrierException { final CyclicBarrierTest instance = new CyclicBarrierTest(); /** * 每個線程代表一個學生 */ for (int i = 0; i < instance.STUDENT_COUNT; i++) { new Thread("學生" + i +" " ) { public void run() { try { instance.goHome(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }; }.start(); } } }
輸出結果:
學生1 已刷卡,等待開門回家~ 學生3 已刷卡,等待開門回家~ 學生5 已刷卡,等待開門回家~ 學生9 已刷卡,等待開門回家~ 學生7 已刷卡,等待開門回家~ 學生0 已刷卡,等待開門回家~ 學生2 已刷卡,等待開門回家~ 學生6 已刷卡,等待開門回家~ 學生8 已刷卡,等待開門回家~ 學生4 已刷卡,等待開門回家~ 人到齊了,開門.... 學生4 放學回家~ 學生1 放學回家~ 學生3 放學回家~ 學生5 放學回家~ 學生9 放學回家~ 學生2 放學回家~ 學生6 放學回家~ 學生0 放學回家~ 學生7 放學回家~ 學生8 放學回家~
哈哈,如果哪個幼兒園用了這么一套系統,孩子應該不會丟學校了吧,,,,開玩笑了;;
CyclicBarrier把所有的線程都阻塞在一個閥門位置,然后等到等待的線程數到達預設的值,就打開這個閥門。記得是阻塞線程,不是阻塞操作,在同一個線程使勁掉await是沒什么效果的。
上面的例子顯示了CyclicBarrier的基本用法,但是cyclic的功能并沒有顯示出來,既然注釋中講了,我們有必要來個例子看看:
我們改造下我們的門禁,畢竟刷卡好不現實,現在需求是這樣的:學生一個人走太危險,現在門衛放學在門口守著,讓學生3個一組的走。
package com.zhy.concurrency.cyclic; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * 改造后的門禁系統 * * @author zhy * */ public class CyclicBarrierTest2 { /** * 學生總數 */ private final int STUDENT_COUNT = 12; /** * 每3個人一組出門 */ final CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println("有3個學生到齊了,放行...."); } }); public void goHome() throws InterruptedException, BrokenBarrierException { System.out.println(Thread.currentThread().getName() + "已刷卡,等待開門回家~"); barrier.await(); } public static void main(String[] args) throws InterruptedException, BrokenBarrierException { final CyclicBarrierTest2 instance = new CyclicBarrierTest2(); /** * 每個線程代表一個學生 */ for (int i = 0; i < instance.STUDENT_COUNT; i++) { new Thread("學生" + i +" " ) { public void run() { try { instance.goHome(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }; }.start(); } } }輸出結果:
學生0 已刷卡,等待開門回家~ 學生1 已刷卡,等待開門回家~ 學生2 已刷卡,等待開門回家~ 有3個學生到齊了,放行.... 學生3 已刷卡,等待開門回家~ 學生5 已刷卡,等待開門回家~ 學生7 已刷卡,等待開門回家~ 有3個學生到齊了,放行.... 學生4 已刷卡,等待開門回家~ 學生9 已刷卡,等待開門回家~ 學生6 已刷卡,等待開門回家~ 有3個學生到齊了,放行.... 學生11 已刷卡,等待開門回家~ 學生10 已刷卡,等待開門回家~ 學生8 已刷卡,等待開門回家~ 有3個學生到齊了,放行....
這個例子充分的體現了CyclicBarrier的復用性,是吧,這樣的系統或許更實在些,0成本~哈哈~。
好了,有興趣的歡迎留言、
來自: http://blog.csdn.net//lmj623565791/article/details/26829117
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!