目录
一、概述
二、CountDownLatch与join的异同
三、源码解析
3.1、await方法源码解析
3.2、downCount方法源码解析
一、概述
作用:可以用来确保某些活动直到其他活动都完成后才继续执行。它是一个同步工具,一般被称作"计数器",作用大致就是数量达到了某个点之后计数结束,才能继续往下走。可以用作流程控制之类的作用,主流程分成多个子流程,然后主流程在子流程全部结束之前不动(子流程最好是相互独立的,除非能很好的控制两个流程的关联关系),子流程全部结束后主流程开始 *** 作。
应用场景:CountDownLatch非常适合于对任务进行拆分,使其并行执行,比如某个任务执行2s,其对数据的请求可以分为五个部分,那么就可以将这个任务拆分为5个子任务,分别交由五个线程执行,执行完成之后再由主线程进行汇总,此时,总的执行时间将决定于执行最慢的任务,平均来看,还是大大减少了总的执行时间。
使用说明:
CountDowmLatch是一种灵活的闭锁实现,包含一个计数器,该计算器初始化为一个正数,表示需要等待事件的数量。countDown方法递减计数器,表示有一个事件发生,而await方法等待计数器到达0,表示所有需要等待的事情都已经完成。
1. 在一组执行 *** 作的多个线程中,当完成了指定 *** 作后,就调用 CountDownLatch 实例的 downCount() 方法,将里面的计数器进行减一的 *** 作,当count==0时,会唤醒正在等待的线程
2. 在需要等待的线程中,通过调用 await() 方法进行等待,直到count ==0 后,等待线程继续往后执行。
PS: 注意downCount() 方法最好是在finally 中被调用, 否则容易因为异常而导致count 不能被赋值成0,从而等待线程一直被阻塞等待。
使用步骤:
1、主线程和子线程都有一个CountDowmLatch类型的成员变量;
2、new一个CountDowmLatch对象countDowmLatch,在创建主线程和子线程时都将countDowmLatch对象作为参数传入;
3、在主线程中调用await方法,countDowmLatch.await();
4、在子线程中调用downCount方法,countDowmLatch.downCount();
注意事项:
使用CountDownLatch必须确保计数器数量与子线程数量一致,且countDown必须要执行,否则出现计数器不为0,导致主线程一致等待的情况。
在执行任务的线程中,使用了try...finally结构,该结构可以保证创建的线程发生异常时CountDownLatch.countDown()方法也会执行,也就保证了主线程不会一直处于等待状态。
示例代码:
package com.flychuer.demo3; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountDownLatchTest { public static void main(String[] args) throws InterruptedException { //CountDownLatch的计数器数量必须与线程的数量一致,否则可能出现一直等待的情况,即计数器不为0的情况 //使用CountDownLatch 需要注意,子线程中的countDown()最好放到finnally里面,防止计数器不为0 CountDownLatch latch = new CountDownLatch(3); ExecutorService ex = Executors.newCachedThreadPool(); ex.execute(new Worker(latch)); ex.execute(new Worker(latch)); ex.execute(new Worker(latch)); System.out.println("主线程等待子线程执行"); //latch.await(1,TimeUnit.SECONDS);//模拟超时等待的情况 latch.await(); //模拟等待的情况,不考虑子线程的处理实际 System.out.println("主线程开始执行"); ex.shutdown(); } } class Worker implements Runnable { CountDownLatch lanch; public Worker() { } public Worker(CountDownLatch lanch) { this.lanch = lanch; } @Override public void run() { try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getId()+":子线程正在执行"); lanch.countDown(); } }
结果:
二、CountDownLatch与join的异同主线程等待子线程执行
11:子线程正在执行
10:子线程正在执行
12:子线程正在执行
主线程开始执行
相同点:
都可以实现主线程等待其它子线程执行完成后,再继续执行的功能。
不同点:
1、join是Thread类的一个方法;CountDownLatch是一个类。
2、join()的阻塞原理是不停检查join()所属的线程对象是否存活(也就是线程完全执行完毕),如果存活则让调用join()的线程保持阻塞。
3、CountDownLatch的阻塞原理是仅仅关注计数器是否为0,若为0才保持阻塞,它并不关注持有计数器的其它线程是否完全执行完毕。
4、CountDownLatch更灵活,它可以只等待子线程执行一部分,而不是等子线程全部执行完成。例如,子线程分为两步,可以在完成第一步后调用downCount()。
三、源码解析 3.1、await方法源码解析 3.2、downCount方法源码解析欢迎分享,转载请注明来源:内存溢出
评论列表(0条)