CountDownLatch 是一种同步辅助工具, 它允许一个或多个线程等待 直到其它线程的一组操作完成。JDK 1.5加入 。
给定count可以获取CountDownLatch对象。类似于一种记数器,通过getCount()可获知还有多少线程没有执行完成。调用await()方法表示进入阻塞,直到count变成0, 程序方可执行下去。
主线程Tm,调用具体执行业务内容的异步线程组(T0,T1,T2,T3),接下来调用await()方法,让主线程进行等待中。 当前count=4。 异步线程组中的每个线程执行完成后,都 会调用countDown(),表示对count进行减1操作。当四个线程全部执行完成,count==0,则主线程Tm继续往下执行。
构造函数:CountDownLatch latch = new CountDownLatch(count)
需要注意的是,初始化CountDownLatch时的count必需与异步线程组的线程数保持一致,线程数多或少于count,会出现永远等待或业务没有执行完成主线程就往下执行了。
主要的应用场景: 一个业务分多步骤,每个步骤中又分多个并行子模块,子模块全部完成才能进行到下一步。 比如,一张综合性报表是由几张小报表汇总而成,必需要先执行完所有的小报表,方可执行综合性报表汇总。
核心方法:
countDown(): 减少计数, 如果计数为0,则释放所有的等待线程。 如果计数大于0,则进行计数减1; 如果计数=0,则什么都不会发生。
await():线程阻塞。1、计数count=0,2、线程发生interrupt异常。 如果计数=0,则方法立即返回。
await(long timeout, TimeUnit unit):线程阻塞。1、计数count=0;2、线程发生interrupt异常;3、等待超时。
代码实现:
第一种:
public void run1(){ LocalDateTime beginTime = LocalDateTime.now(); Thread[] threads = new Thread[10]; CountDownLatch latch = new CountDownLatch(threads.length); for (int i=0;i<threads.length;i++){ threads[i] = new Thread(()->{ /** * 执行业务流程 */ try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } latch.countDown(); System.out.println(LocalDateTime.now()+"==="+Thread.currentThread().getName()); },"t"+i); } for (Thread t : threads){ t.start(); } try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(beginTime+"---------end latch>>>>"+LocalDateTime.now()); }
第二种:使用线程池
public void run2() { LocalDateTime beginTime = LocalDateTime.now(); int threadCount = 10 ; CountDownLatch doneLatch = new CountDownLatch(threadCount); Executor executor = Executors.newFixedThreadPool(threadCount); for (int i = 0; i < threadCount; i++) { executor.execute(new WorkRunnable(doneLatch, i)); } try { doneLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(beginTime+"---------end latch>>>>"+LocalDateTime.now()); } class WorkRunnable implements Runnable { private CountDownLatch latch ; private int index; public WorkRunnable(CountDownLatch latch, int index){ this.latch = latch; this.index = index; } @Override public void run() { /** * 执行业务流程 */ try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } latch.countDown(); System.out.println(LocalDateTime.now()+" => "+index); } }