在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

Java 并发专题 : CyclicBarrier 打造一个安全的门禁系统

2017-2-7 13:39| 发布者: zhangjf| 查看: 480| 评论: 0

摘要: 继续并发专题~ 这次介绍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 * us ...

继续并发专题~

这次介绍CyclicBarrier:看一眼API的注释:

  1. /**
  2. * A synchronization aid that allows a set of threads to all wait for
  3. * each other to reach a common barrier point. CyclicBarriers are
  4. * useful in programs involving a fixed sized party of threads that
  5. * must occasionally wait for each other. The barrier is called
  6. * <em>cyclic</em> because it can be re-used after the waiting threads
  7. * are released.
复制代码

大概意思:一个让一组线程同时阻塞到一个位置的同步辅助类。在包含固定线程且线程间必须相互等待的场景中非常有用。cyclic的意思是CyclicBarrier当等待的线程全部释放之后,可以重复使用。(英语水平就这样了。。。。)

CyclicBarrier 类似一个闸门,指定数目的线程都必须到达这个闸门,闸门才会打开。

下面使用CyclicBarrier模拟一个门禁系统:

需求是这样的:到放学时间,所有的学生必须刷卡,然后人数齐了自动开门,统一回家。这个需求刚刚的,避免了把部分孩子丢在学校发生危险,特别是幼儿园或者小学生~~

  1. package com.zhy.concurrency.cyclic;
  2. import java.util.concurrent.BrokenBarrierException;
  3. import java.util.concurrent.CyclicBarrier;
  4. /**
  5. * 安全的门禁系统
  6. *
  7. * @author zhy
  8. *
  9. */
  10. public class CyclicBarrierTest
  11. {
  12. /**
  13. * 学生总数
  14. */
  15. private final int STUDENT_COUNT = 10;
  16. /**
  17. * 当人到齐,自动开门程序
  18. */
  19. final CyclicBarrier barrier = new CyclicBarrier(STUDENT_COUNT,
  20. new Runnable()
  21. {
  22. @Override
  23. public void run()
  24. {
  25. System.out.println("人到齐了,开门....");
  26. }
  27. });
  28. public void goHome() throws InterruptedException, BrokenBarrierException
  29. {
  30. System.out.println(Thread.currentThread().getName() + "已刷卡,等待开门回家~");
  31. barrier.await();
  32. System.out.println(Thread.currentThread().getName() + "放学回家~");
  33. }
  34. public static void main(String[] args) throws InterruptedException,
  35. BrokenBarrierException
  36. {
  37. final CyclicBarrierTest instance = new CyclicBarrierTest();
  38. /**
  39. * 每个线程代表一个学生
  40. */
  41. for (int i = 0; i < instance.STUDENT_COUNT; i++)
  42. {
  43. new Thread("学生" + i +" " )
  44. {
  45. public void run()
  46. {
  47. try
  48. {
  49. instance.goHome();
  50. } catch (InterruptedException e)
  51. {
  52. e.printStackTrace();
  53. } catch (BrokenBarrierException e)
  54. {
  55. e.printStackTrace();
  56. }
  57. };
  58. }.start();
  59. }
  60. }
  61. }
复制代码

输出结果:

  1. 学生1 已刷卡,等待开门回家~
  2. 学生3 已刷卡,等待开门回家~
  3. 学生5 已刷卡,等待开门回家~
  4. 学生9 已刷卡,等待开门回家~
  5. 学生7 已刷卡,等待开门回家~
  6. 学生0 已刷卡,等待开门回家~
  7. 学生2 已刷卡,等待开门回家~
  8. 学生6 已刷卡,等待开门回家~
  9. 学生8 已刷卡,等待开门回家~
  10. 学生4 已刷卡,等待开门回家~
  11. 人到齐了,开门....
  12. 学生4 放学回家~
  13. 学生1 放学回家~
  14. 学生3 放学回家~
  15. 学生5 放学回家~
  16. 学生9 放学回家~
  17. 学生2 放学回家~
  18. 学生6 放学回家~
  19. 学生0 放学回家~
  20. 学生7 放学回家~
  21. 学生8 放学回家~
复制代码

哈哈,如果哪个幼儿园用了这么一套系统,孩子应该不会丢学校了吧,,,,开玩笑了;;

CyclicBarrier把所有的线程都阻塞在一个阀门位置,然后等到等待的线程数到达预设的值,就打开这个阀门。记得是阻塞线程,不是阻塞操作,在同一个线程使劲掉await是没什么效果的。


上面的例子显示了CyclicBarrier的基本用法,但是cyclic的功能并没有显示出来,既然注释中讲了,我们有必要来个例子看看:

我们改造下我们的门禁,毕竟刷卡好不现实,现在需求是这样的:学生一个人走太危险,现在门卫放学在门口守着,让学生3个一组的走。

  1. package com.zhy.concurrency.cyclic;
  2. import java.util.concurrent.BrokenBarrierException;
  3. import java.util.concurrent.CyclicBarrier;
  4. /**
  5. * 改造后的门禁系统
  6. *
  7. * @author zhy
  8. *
  9. */
  10. public class CyclicBarrierTest2
  11. {
  12. /**
  13. * 学生总数
  14. */
  15. private final int STUDENT_COUNT = 12;
  16. /**
  17. * 每3个人一组出门
  18. */
  19. final CyclicBarrier barrier = new CyclicBarrier(3,
  20. new Runnable()
  21. {
  22. @Override
  23. public void run()
  24. {
  25. System.out.println("有3个学生到齐了,放行....");
  26. }
  27. });
  28. public void goHome() throws InterruptedException, BrokenBarrierException
  29. {
  30. System.out.println(Thread.currentThread().getName() + "已刷卡,等待开门回家~");
  31. barrier.await();
  32. }
  33. public static void main(String[] args) throws InterruptedException,
  34. BrokenBarrierException
  35. {
  36. final CyclicBarrierTest2 instance = new CyclicBarrierTest2();
  37. /**
  38. * 每个线程代表一个学生
  39. */
  40. for (int i = 0; i < instance.STUDENT_COUNT; i++)
  41. {
  42. new Thread("学生" + i +" " )
  43. {
  44. public void run()
  45. {
  46. try
  47. {
  48. instance.goHome();
  49. } catch (InterruptedException e)
  50. {
  51. e.printStackTrace();
  52. } catch (BrokenBarrierException e)
  53. {
  54. e.printStackTrace();
  55. }
  56. };
  57. }.start();
  58. }
  59. }
  60. }
复制代码
输出结果:

  1. 学生0 已刷卡,等待开门回家~
  2. 学生1 已刷卡,等待开门回家~
  3. 学生2 已刷卡,等待开门回家~
  4. 有3个学生到齐了,放行....
  5. 学生3 已刷卡,等待开门回家~
  6. 学生5 已刷卡,等待开门回家~
  7. 学生7 已刷卡,等待开门回家~
  8. 有3个学生到齐了,放行....
  9. 学生4 已刷卡,等待开门回家~
  10. 学生9 已刷卡,等待开门回家~
  11. 学生6 已刷卡,等待开门回家~
  12. 有3个学生到齐了,放行....
  13. 学生11 已刷卡,等待开门回家~
  14. 学生10 已刷卡,等待开门回家~
  15. 学生8 已刷卡,等待开门回家~
  16. 有3个学生到齐了,放行....
复制代码

这个例子充分的体现了CyclicBarrier的复用性,是吧,这样的系统或许更实在些,0成本~哈哈~。


好了,有兴趣的欢迎留言、

来自: http://blog.csdn.net//lmj623565791/article/details/26829117

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-9 08:14

Copyright 2015-2025 djqfx

返回顶部