CountDownLatch类
允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成了任务,然后在CountDownLatch上等待的线程就可以恢复执行任务。
构造方法:
CountDownLatch(int count)
构造一个以给定计数 CountDownLatch CountDownLatch。
方法:
- await() 导致当前线程等到锁存器计数到零,除非线程是 interrupted 。
- await(long timeout, TimeUnit unit) 使当前线程等待直到锁存器计数到零为止,除非线程为 interrupted或指定的等待时间过去。
- countDown() 减少锁存器的计数,如果计数达到零,释放所有等待的线程。
- getCount() 返回当前计数。
模拟运动员赛跑DEMO
1 import concurrenttest.countdownlatch.thread.Thread_1; 2 3 import java.util.concurrent.CountDownLatch; 4 5 /** 6 * 描述:模拟运动员赛跑DEMO 7 * 8 * @author bc 9 * @create 2018-09-28 10:49 10 */ 11 public class RunTest_1 { 12 13 public static void main(String[] args) { 14 try { 15 CountDownLatch comingTag = new CountDownLatch(10);//裁判等待运动员到来 16 CountDownLatch waitTag = new CountDownLatch(1);//等待裁判说准备开始 17 CountDownLatch waitRunTag = new CountDownLatch(10);//等待起跑 18 CountDownLatch beginTag = new CountDownLatch(1);//起跑 19 CountDownLatch endTag = new CountDownLatch(10);//到达终点 20 21 Thread_1[] arr = new Thread_1[10]; 22 for (int i = 0; i < arr.length; i++) { 23 arr[i] = new Thread_1(comingTag, waitTag, waitRunTag, beginTag, endTag); 24 arr[i].start(); 25 } 26 27 System.out.println("裁判等待运动员到来"); 28 comingTag.await(); 29 System.out.println("裁判看到所有运动员都来了,巡视一下"); 30 Thread.sleep(5000); 31 waitTag.countDown(); 32 System.out.println("各就各位!"); 33 waitRunTag.await(); 34 Thread.sleep(2000); 35 System.out.println("发令枪响!"); 36 beginTag.countDown(); 37 endTag.await(); 38 System.out.println("所有运动员到了,统计结果"); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } 42 43 } 44 }
1 import java.util.concurrent.CountDownLatch; 2 3 /** 4 * 描述: 模拟运动员赛跑 5 * 6 * @author bc 7 * @create 2018-09-28 10:10 8 */ 9 public class Thread_1 extends Thread { 10 11 private CountDownLatch comingTag;//裁判等待运动员到来 12 private CountDownLatch waitTag;//等待裁判说准备开始 13 private CountDownLatch waitRunTag;//等待起跑 14 private CountDownLatch beginTag;//起跑 15 private CountDownLatch endTag;//到达终点 16 17 public Thread_1(CountDownLatch comingTag, CountDownLatch waitTag, CountDownLatch waitRunTag, 18 CountDownLatch beginTag, CountDownLatch endTag) { 19 super(); 20 this.comingTag = comingTag; 21 this.waitTag = waitTag; 22 this.waitRunTag = waitRunTag; 23 this.beginTag = beginTag; 24 this.endTag = endTag; 25 } 26 27 @Override 28 public void run() { 29 try { 30 System.out.println("运动员正飞奔而来"); 31 Thread.sleep((int)(Math.random()*10000)); 32 System.out.println(Thread.currentThread().getName()+"到起跑点了"); 33 comingTag.countDown(); 34 System.out.println("等待裁判说准备"); 35 waitTag.await(); 36 System.out.println("各就各位!准备起跑的姿势"); 37 Thread.sleep((int)(Math.random()*10000)); 38 waitRunTag.countDown(); 39 beginTag.await(); 40 System.out.println(Thread.currentThread().getName()+"疯狂奔跑中"); 41 Thread.sleep((int)(Math.random()*10000)); 42 endTag.countDown(); 43 System.out.println(Thread.currentThread().getName()+"到达终点"); 44 } catch (InterruptedException e) { 45 e.printStackTrace(); 46 } 47 48 } 49 }
CountDownLatch的不足
CountDownLatch是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,它不能再次被使用。
详见本人github:https://github.com/BrokenColor/java-demo 下的 countdownlatch-包中的测试