介绍

CountDownLatch 是Concurrent包中的一个辅助类,可以把他看成是一个计数器,其内部维护着一个count计数,只不过这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器,CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CountDownLatc对象的cutDown()方法来使计数器减1,如果调用者调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到其他线程调用cutDown()来使计数器值为0,才可以继续执行

应用场景

例如文件下载,3个线程分别去下载文件的1/3段,等3个线程全部工作完毕后由另外一个线程去拼接文件,从而完成工作

代码使用

import com.enjoy.demo.p1.ch1.class1.SleepTools;

import java.util.concurrent.CountDownLatch;

/**
 * @Author: BillYu
 * @Description:演示CountDownLatch 有5个初始化的线程 6个扣除点
 * 扣除完毕以后,主线程和业务线程才能继续自己的工作
 *
 * 作用:是一个线程等待其他的线程完成工作以后再执行,countDown负责计数器的减一
 *
 * @Date: Created in 10:51 2019-02-26.
 */
public class UseCountDownLatch {
    static CountDownLatch latch = new CountDownLatch(6);

    /**
     * 初始化线程
     */
    private static class InitThread implements Runnable{


        @Override
        public void run() {
            System.out.println("Thread_"+Thread.currentThread().getId()+" ready init work....");
            //初始化线程完成工作了,countDown只扣减一次
            latch.countDown();
            for (int i=0;i<2;i++){
                System.out.println("Thread_"+Thread.currentThread().getId()+" ...continue do its work");
            }

        }
    }

    /**
     * 业务线程
     */
    private static class BusiThread implements Runnable{

        @Override
        public void run() {
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i=0;i<3;i++){
                System.out.println("BusiThread_"+Thread.currentThread().getId()+" do business");
            }
        }
    }


    public static void main(String[] args) {
        //单独的初始化线程,初始化分为2步,需要扣减2次
        new Thread(new Runnable() {
            @Override
            public void run() {
                SleepTools.ms(1);
                System.out.println("Thread_"+Thread.currentThread().getId()+" ready init work step 1st...");
                //每完成一步初始化工作,扣减一次
                latch.countDown();
                System.out.println("begin step 2nd...");
                SleepTools.ms(1);
                System.out.println("Thread_"+Thread.currentThread().getId()+" ready init work step 2nd...");
                //每完成一步初始化工作,扣减一次
                latch.countDown();
            }
        }).start();

        new Thread(new BusiThread()).start();
        for (int i =0;i<=3;i++){
            Thread thread = new Thread(new InitThread());
            thread.start();
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Main work is finished");


    }
}

初始化线程调用latch.countDown(),等待全部扣减完毕后 业务线程被唤醒进行业务处理