什么是CountDownLatch?
这是一种可以使得某个线程等待其他线程完成各自工作之后,同步执行的一个工具类。
原理:
通过一个计数器,初始值为所有线程的数量,当线程开启之后,数值减少1,当数值为0的时候,表示所有线程已经完成任务。
网络异常,图片无法展示
|
CountDownLatch如何工作
构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
接下来举个demo来进行案例讲解:
package 并发编程12.CountDownLatch模块; /** * @author idea * @data 2019/1/28 */ public class Service { public void testMethod() throws InterruptedException { System.out.println(Thread.currentThread().getName()+"begin timer"+System.currentTimeMillis()); Thread.sleep((long) (Math.random()*1000)); System.out.println(Thread.currentThread().getName()+"end timer"+System.currentTimeMillis()); } } package 并发编程12.CountDownLatch模块; import lombok.Data; import java.util.concurrent.CountDownLatch; /** * @author idea * @data 2019/1/28 */ @Data public class MyThread extends Thread { private Service service; private final CountDownLatch begin; private final CountDownLatch end; public MyThread(Service service, CountDownLatch begin, CountDownLatch end) { this.service = service; this.begin = begin; this.end = end; } @Override public void run() { try { begin.await(); //会堵塞当前线程 直到N变为0,如果该线程一直堵塞,不妨可以尝试一下await中加入相关时间参数来控制 // begin.await(2,TimeUnit.SECONDS); service.testMethod(); } catch (InterruptedException e) { e.printStackTrace(); } end.countDown(); } public Service getService() { return service; } public MyThread setService(Service service) { this.service = service; return this; } public CountDownLatch getBegin() { return begin; } public CountDownLatch getEnd() { return end; } } . 复制代码
接下来是测试模块
package 并发编程12.CountDownLatch模块; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * @author idea * @data 2019/1/28 */ public class Test { public static void main(String[] args) throws InterruptedException { Service service=new Service(); CountDownLatch begin=new CountDownLatch(1); //如果设置的countdownLatch过多,那么总线程就会一直不开始,如果数量过少,则只会对部分线程有效 CountDownLatch end=new CountDownLatch(10); MyThread[] threadArray=new MyThread[10]; for(int i=0;i<10;i++){ threadArray[i]=new MyThread(service,begin,end); threadArray[i].setName(i+"号选手"); threadArray[i].start(); } System.out.println("等待裁判员开枪!"+System.currentTimeMillis()); long t1=System.currentTimeMillis(); //开始执行线程 堵塞主线程 begin.countDown(); //等待10个子线程执行完毕之后再执行,如果不想一直等待,可以设置时间 end.await(1,TimeUnit.MILLISECONDS); System.out.println("比赛结束,时间为:"+System.currentTimeMillis()); } } 复制代码
CountDownLatch 类里面提供的主要方法有哪些?
CountDownLatch(int count) void await() boolean await(long timeout, TimeUnit unit) void countDown() long getCount()