Java并发工具类-CountDownLatch

一、简述

  CountDownLatch是一个用来控制并发的很常见的工具,它是java.util.concurrent包中一个类,CountDownLatch主要提供的机制是当多个(具体数量等于初始化CountDownLatch时count参数的值)线程都达到了预期状态或完成预期工作时触发事件,其他线程可以等待这个事件来触发自己的后续工作。到达自己预期状态的线程会调用CountDownLatch的countDown方法,而等待的线程会调用CountDownLatch的await方法。

  CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果想要等待N个点完成,这里就传入N。

  如果某个工作线程处理的比较慢,我们不能让主线程一直等待下去。所以可以使用另外一个带指定时间的await方法----await(long time,TimeTnit unit),这个方法等待制定时间后,就不会阻塞当前线程。

  注意:计数器必须大于等于0,当计数器等于0时,调用await方法不会阻塞当前线程;

二、CountDownLatch使用示例

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(2);//两个线程工作
        new Worker("work1", 200, latch).start();
        new Worker("work2", 300, latch).start();
        latch.await();//等待所有线程完成
        System.out.println("工作全部完成");
    }

    static class Worker extends Thread {
        String workName;
        int workTime;
        CountDownLatch latch;

        public Worker(String workName, int workTime, CountDownLatch latch) {
            this.workName = workName;
            this.workTime = workTime;
            this.latch = latch;
        }

        public void run() {
            System.out.println(workName + "开始工作");
            doWork();
            System.out.println(workName + "结束工作");
            latch.countDown();//完成工作,计数器减一  
        }

        private void doWork() {
            try {
                Thread.sleep(workTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

三、与join的比较

  相比于同样可以让一个线程等待子线程完成的join,CountDownLatch通过计数器提供了更灵活的控制,调用countDown方法是,N就会减1,CountDownLatch的await方法会阻塞当前线程,知道N变为0,由于countDown方法可以用在任何地方,所以这里说的N个点可以是N个线程,也可以是N个执行步骤。

  而join是用于让当前线程等待JOIN线程执行结束。其实现原理是不停检查JOIN线程是否存活,如果JOIN线程存活则让当前线程永远等待。

示例如下:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(2);//两个线程工作
        new Worker("work1", 200, latch).start();
        new Worker("work2", 300, latch).start();
        latch.await();//等待所有线程完成
        System.out.println("工作全部完成");
    }

    static class Worker extends Thread {
        String workName;
        int workTime;
        CountDownLatch latch;

        public Worker(String workName, int workTime, CountDownLatch latch) {
            this.workName = workName;
            this.workTime = workTime;
            this.latch = latch;
        }

        public void run() {
            System.out.println(workName + "开始工作");
            doWork();
            System.out.println(workName + "结束工作");
            latch.countDown();//完成工作,计数器减一  
            System.out.println(workName + "开始第二阶段工作");
            doWork();
            System.out.println(workName + "结束第二阶段工作");
        }

        private void doWork() {
            try {
                Thread.sleep(workTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

打印结果如下:

work1开始工作
work2开始工作
work1结束工作
work1开始第二阶段工作
work2结束工作
工作全部完成
work2开始第二阶段工作
work1结束第二阶段工作
work2结束第二阶段工作
原文地址:https://www.cnblogs.com/ljch/p/12129176.html