转自:

  http://www.cnblogs.com/dolphin0520/p/3920397.html

1.简介

  • CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同。
  • CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行
  • CyclicBarrier 回环栅栏,一般用于一组线程互相等待至某个状态,然后这一组线程再同时开始执行后续任务
  • CountDownLatch 在使用完后不可重用
  • CyclicBarrier 使用完后可重用
  • Semaphore 信号量,一般用于控制对某组资源的访问权限。

2.CountDownLatch示例

  1. void testCountDownLatch() {
  2. final CountDownLatch latch = );
  3. new Thread() {
  4. public void run() {
  5. try {
  6. Log.d(TAG, "子线程" + Thread.currentThread().getName() + "正在执行");
  7. Thread.sleep();
  8. Log.d(TAG, "子线程" + Thread.currentThread().getName() + "执行完毕");
  9. latch.countDown();
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. }
  14.  
  15. ;
  16. }.start();
  17.  
  18. new Thread() {
  19. public void run() {
  20. try {
  21. Log.d(TAG, "子线程" + Thread.currentThread().getName() + "正在执行");
  22. Thread.sleep();
  23. Log.d(TAG, "子线程" + Thread.currentThread().getName() + "执行完毕");
  24. latch.countDown();
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29.  
  30. ;
  31. }.start();
  32.  
  33. try {
  34. Log.d(TAG, "等待2个子线程执行完毕...");
  35. latch.await();
  36. Log.d(TAG, "2个子线程已经执行完毕");
  37. Log.d(TAG, "继续执行主线程");
  38. } catch (InterruptedException e) {
  39. e.printStackTrace();
  40. }
  41. }

3.CyclicBarrier示例

  1. static class Writer extends Thread {
  2. private CyclicBarrier cyclicBarrier;
  3.  
  4. public Writer(CyclicBarrier cyclicBarrier) {
  5. this.cyclicBarrier = cyclicBarrier;
  6. }
  7.  
  8. @Override
  9. public void run() {
  10. Log.d(TAG, "线程" + Thread.currentThread().getName() + "正在写入数据...");
  11. try {
  12. Thread.sleep(); //以睡眠来模拟写入数据操作
  13. Log.d(TAG, "线程" + Thread.currentThread().getName() + "写入数据完毕,等待其他线程写入完毕");
  14. cyclicBarrier.await();
  15. } catch (InterruptedException e) {
  16. e.printStackTrace();
  17. } catch (BrokenBarrierException e) {
  18. e.printStackTrace();
  19. }
  20. Log.d(TAG, "所有线程写入完毕,继续处理其他任务...");
  21. }
  22. }
  23.  
  24. //用来阻塞当前线程,直至所有线程都到达barrier状态再同时执行后续任务;
  25. void testCyclicBarrier1(){
  26. ;
  27. CyclicBarrier barrier = new CyclicBarrier(N);
  28. ; i < N; i++) {
  29. new Writer(barrier).start();
  30. }
  31. }
  32.  
  33. //如果说想在所有线程写入操作完之后,进行额外的其他操作可以为CyclicBarrier提供Runnable参数
  34. void testCyclicBarrier2(){
  35. ;
  36. CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() {
  37. @Override
  38. public void run() {
  39. Log.d(TAG, "当前线程" + Thread.currentThread().getName());
  40. }
  41. });
  42.  
  43. ; i < N; i++){
  44. new Writer(barrier).start();
  45. }
  46. }
  47.  
  48. //CyclicBarrier是可以重用的
  49. void testCyclicBarrier3(){
  50. ;
  51. CyclicBarrier barrier = new CyclicBarrier(N);
  52.  
  53. ; i < N; i++) {
  54. new Writer(barrier).start();
  55. }
  56.  
  57. try {
  58. Thread.sleep();
  59. } catch (InterruptedException e) {
  60. e.printStackTrace();
  61. }
  62.  
  63. Log.d(TAG, "CyclicBarrier重用");
  64.  
  65. ; i < N; i++) {
  66. new Writer(barrier).start();
  67. }
  68. }
  69.  
  70. //故意让最后一个线程启动延迟,因为在前面三个线程都达到barrier之后,
  71. //等待了指定的时间发现第四个线程还没有达到barrier,就抛出异常并继续执行后面的任务。
  72. void testCyclicBarrier4(){
  73.  
  74. ;
  75. CyclicBarrier barrier = new CyclicBarrier(N);
  76.  
  77. ; i < N; i++) {
  78. )
  79. new Writer2(barrier).start();
  80. else {
  81. try {
  82. Thread.sleep();
  83. } catch (InterruptedException e) {
  84. e.printStackTrace();
  85. }
  86. new Writer(barrier).start();
  87. }
  88. }
  89. }
  90. static class Writer2 extends Thread{
  91. private CyclicBarrier cyclicBarrier;
  92. public Writer2(CyclicBarrier cyclicBarrier) {
  93. this.cyclicBarrier = cyclicBarrier;
  94. }
  95.  
  96. @Override
  97. public void run() {
  98. Log.d(TAG, "线程"+Thread.currentThread().getName()+"正在写入数据...");
  99. try {
  100. Thread.sleep(); //以睡眠来模拟写入数据操作
  101. Log.d(TAG, "线程"+Thread.currentThread().getName()+"写入数据完毕,等待其他线程写入完毕");
  102. try {
  103. cyclicBarrier., TimeUnit.MILLISECONDS);//等待了指定的时间(2ms)发现第四个线程还没有达到barrier,就抛出异常并继续执行后面的任务
  104. } catch (TimeoutException e) {
  105. // TODO Auto-generated catch block
  106. e.printStackTrace();
  107. }
  108. } catch (InterruptedException e) {
  109. e.printStackTrace();
  110. }catch(BrokenBarrierException e){
  111. e.printStackTrace();
  112. }
  113. Log.d(TAG, Thread.currentThread().getName()+"所有线程写入完毕,继续处理其他任务...");
  114. }
  115. }

4.Semaphore示例

  1. void testSemaphore() {
  2. ; //工人数
  3. Semaphore semaphore = ); //机器数目
  4. ; i < N; i++)
  5. new Worker(i, semaphore).start();
  6. }
  7.  
  8. static class Worker extends Thread {
  9. private int num;
  10. private Semaphore semaphore;
  11.  
  12. public Worker(int num, Semaphore semaphore) {
  13. this.num = num;
  14. this.semaphore = semaphore;
  15. }
  16.  
  17. @Override
  18. public void run() {
  19. try {
  20. semaphore.acquire();
  21. Log.d(TAG,"工人" + this.num + "占用一个机器在生产...");
  22. Thread.sleep();
  23. Log.d(TAG,"工人" + this.num + "释放出机器");
  24. semaphore.release();
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }

java中的线程(4):常用同步类 CountDownLatch、CyclicBarrier和Semaphore的更多相关文章

  1. Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger

    在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...

  2. Java中Collection、Map常用实现类研究分析

    接口/实现类 描述 key是否可为null 为null是否报错 key是否重复 key重复是否报错 key是否和添加一致 是否线程安全 List 一组元素的集合 ArrayList 基于数组存储,读取 ...

  3. Java中创建线程的三种方式以及区别

    在java中如果要创建线程的话,一般有3种方法: 继承Thread类: 实现Runnable接口: 使用Callable和Future创建线程. 1. 继承Thread类 继承Thread类的话,必须 ...

  4. 浅谈利用同步机制解决Java中的线程安全问题

    我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等 ...

  5. 【Java中的线程】java.lang.Thread 类分析

    进程和线程 联想一下现实生活中的例子--烧开水,烧开水时是不是不需要在旁边守着,交给热水机完成,烧开水这段时间可以去干一点其他的事情,例如将衣服丢到洗衣机中洗衣服.这样开水烧完,衣服洗的也差不多了.这 ...

  6. 关于Java中的线程安全(线程同步)

    java中的线程安全是什么: 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么叫 ...

  7. Java中的线程同步

    Java 中的线程同步问题: 1. 线程同步: 对于访问同一份资源的多个线程之间, 来进行协调的这个东西. 2. 同步方法: 当某个对象调用了同步方法时, 该对象上的其它同步方法必须等待该同步方法执行 ...

  8. JAVA基础——Java 中必须了解的常用类

    Java中必须了解的常用类 一.包装类 相信各位小伙伴们对基本数据类型都非常熟悉,例如 int.float.double.boolean.char 等.基本数据类型是不具备对象的特性的,比如基本类型不 ...

  9. Java中的线程Thread总结

    首先来看一张图,下面这张图很清晰的说明了线程的状态与Thread中的各个方法之间的关系,很经典的! 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口. 要注意的是Threa ...

随机推荐

  1. 7. Smali基础语法总结

    最近在学习Android 移动安全逆向方面,逆向首先要看懂代码,Android4.4之前一直使用的是 Dalivk虚拟机,而Smali是用于Dalivk的反汇编程序的实现. Smali 支持注解,调试 ...

  2. Reportng 的测试报告在 Jenkins 中显示不全

    通过Jenkins执行接口测试生成测试报告,用Jenkins的web服务打开html显示不全. 环境: Jenkins版本:1.651.2 Jenkins发布在mac上面 使用的是testng管理测试 ...

  3. location.reload() 和 location.replace()的区别和应用

    首先介绍两个方法的语法: reload 方法,该方法强迫浏览器刷新当前页面.语法: location.reload([bForceGet]) 参数: bForceGet, 可选参数, 默认为 fals ...

  4. Orace开源的异步IO编程库,特点是接口非常简单

    官网:https://oss.oracle.com/projects/libaio-oracle/,正如标题所说,非常简单了,不用多解释,请直接看头文件,其中aio_poll类似于poll,重要的结构 ...

  5. RPLiDAR 激光雷达探测地面高程

    LiDAR,又称激光探测与测量,全程Light Detection And Ranging,这种技术使用激光测量地物(如森林和建筑物)的高程.它的原理十分类似于使用声波来测绘海底地形的声呐技术,或使用 ...

  6. Redis 占用Windows系统盘空间23G

    Redis常出现问题总结: 1.当出现修改--maxheap and --heapdir 在启动这两个版本时都会创建一个 RedisQFork.dat文件,我不确定 RedisQFork 文件是否变小 ...

  7. 精心收集的 48 个 JavaScript 代码片段,仅需 30 秒就可理解!(转载)

    Anagrams of string(带有重复项) 使用递归.对于给定字符串中的每个字母,为字母创建字谜.使用map()将字母与每部分字谜组合,然后使用reduce()将所有字谜组合到一个数组中,最基 ...

  8. 数组中 reduce累计运算

    let arr = [1,2,3,4]; let sum = (a, b) => a + b; arr.reduce(sum, 0); 最后输出10

  9. ecliplse里tomcat正常启动后http://localhost:8080/报错404

    如下图所示,新建一个工作区间,添加tomcat之后通过ecliplse启动tomcat之后: 访问http://localhost:8080/出现404: 解决方法: 1.确保tomcat里面所有项目 ...

  10. linux 虚拟机 安装 php-7.0.2

    1.安装依赖包 yum -y install libxml2 libxml2-devel openssl openssl-devel libjpeg libjpeg-devel libpng libp ...