多线程 - CountDownLatch总结

Posted Alex_MaHao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程 - CountDownLatch总结相关的知识,希望对你有一定的参考价值。

问题

当主线程的任务执行,需要依赖多个子线程运行结束后才能往下执行时如何解决,比如文件分段下载,同时开启多个子线程进行文件的分段下载,当下载完成之后,再进行组装。

有一种解决方式,便是在子线程下载完成之后,都进行子线程的回调并判断是否所有子线程都已经执行完毕。

CountDownLatch便是java在1.5提供的解决如上问题的工具类

阿里的ARouter的拦截器相关,就是用该工具类

概述

CountDownLatch是通过一个计数器来实现的,计数器的初始值是线程的数量。然后通过调用await()完成阻塞,每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后阻塞会被打开。

使用

初始化CountDownLatch并设置子线程数量

CountDownLatch latch = new CountDownLatch(2);

创建子线程并启动,并在子线程结束时,调用countDown()进行计数器更新

 es1.execute(new Runnable() 
            @Override
            public void run() 
                Thread.sleep(3000);
                System.out.println("子线程:" + Thread.currentThread().getName() + "执行");
                // 核心方法
                latch.countDown();
            
        );

主线程进行等待

latch.await();

该方法同时提供了一个重载方法,可以设置阻塞的时间,如果超时,直接执行,跳过阻塞。

public boolean await(long timeout, TimeUnit unit)

CyclicBarrier比对

  • CountDownLatch执行一次,完成之后就结束了。
  • CyclicBarrier可以使用多次。比如有4个线程,每个线程内部都分为3个子任务,而每个线程都需要保持子任务的同步,即4个线程都执行完自己的第一个任务之后,才开始往下执行第二个任务。

例如

 @Override
        public void run() 
            try 
                Thread.sleep(1000);
                System.out.println(getName() + " 任务1");
                barrier.await();
                
                System.out.println(getName() + " 任务2");
                Thread.sleep(1500);
                barrier.await();
                
                Thread.sleep(2000);
                System.out.println(getName() + " 任务3");
                barrier.await();
                
             catch (Exception e) 
                e.printStackTrace();
            
        

多个run会先打印完任务1才开始打印任务2

以上是关于多线程 - CountDownLatch总结的主要内容,如果未能解决你的问题,请参考以下文章

多线程 - CountDownLatch总结

Java多线程信号量同步类CountDownLatch与Semaphore

多线程等待所有子线程执行完使用总结——CountDownLatch使用和源码初步分析

多线程之倒计时器CountDownLatch和循环栅栏CyclicBarrier

JUC多线程:CountDownLatchCyclicBarrierSemaphore同步器原理总结

多线程之CyclicBarrier详解