CountDownLatch 作用理解示例

CountDownLatch 是Java1.5之后引入的Java并发工具类,在java.util.concurrent包下。

CountDownLatch 是个计数器锁,用于阻塞当前线程,等待其他前程都执行完毕 再继续执行。初始化是需要传入一个int类型的整数:CountDownLatch countDown = new CountDownLatch(5) 表示初始计数器的值表示 线程数。

作用: 使用await()方法阻塞一个或者多个线程,等待 所有线程(初始化个数)都执行完毕 既 计数器为0时(每个线程成功执行之后都调用countDown()方法使计数器减一),唤醒因await()方法等待的线程继续执行。

使用场景例子: 一个任务的某个步骤需要很多小任务,主任务就相当于主线程,分出来各个小任务给其他线程,就可以使用CountDownLatch等待所有的小任务都执行完毕,主任务再往下执行。

官网提供的代码示例:

class Driver { // ...
   void main() throws InterruptedException {
     CountDownLatch startSignal = new CountDownLatch(1);
     CountDownLatch doneSignal = new CountDownLatch(N);

     for (int i = 0; i < N; ++i)   // 创建启动N个子线程
       new Thread(new Worker(startSignal, doneSignal)).start();

     doSomethingElse();            
     startSignal.countDown();      // 主线程执行完毕,唤醒await等待的子线程
     doSomethingElse();
     doneSignal.await();           // 等待N个线程都执行完毕之后再执行
   }
 }

 class Worker implements Runnable {
   private final CountDownLatch startSignal;
   private final CountDownLatch doneSignal;
   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
      this.startSignal = startSignal;
      this.doneSignal = doneSignal;
   }
   public void run() {
      try {
        startSignal.await();     //等到主线程startSignal.countDown()执行完之后再开始执行
        doWork();
        doneSignal.countDown();  //每次执行完计数器 N 减去一 ,为0时唤醒主线程继续执行。
      } catch (InterruptedException ex) {
      } // return;
   }

   void doWork() { ... }
 }

例子:

package crzis2;

import java.util.concurrent.CountDownLatch;

/**
 * @author Crzis
 * @title: CountDownLatchTest
 * @description: TODO
 * @date 2019/7/29 15:16
 */
public class CountDownLatchTest {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDown = new CountDownLatch(1);
        CountDownLatch await = new CountDownLatch(5);

        // 依次创建并启动处于等待状态的5个MyRunnable线程
        for (int i = 0; i < 5; ++i) {
            new Thread(new MyRunnable(countDown, await)).start();
        }

        System.out.println("主线程开始工作...");

        System.out.println("当前countDown的值为:" + countDown.getCount());
        countDown.countDown();
        System.out.println("当前countDown的值为:" + countDown.getCount());

        System.out.println("当前await的值为:" + await.getCount());
        System.out.println("主线程开始等待...");
        await.await();
        System.out.println("当前await的值为:" + await.getCount());
        System.out.println("所有子线程线程执行完毕,主线程继续执行!");
    }

     static class MyRunnable implements Runnable {

        private final CountDownLatch countDown;
        private final CountDownLatch await;

        public MyRunnable(CountDownLatch countDown, CountDownLatch await) {
            this.countDown = countDown;
            this.await = await;
        }

        public void run() {
            try {
                countDown.await();  //等待主线程执行countDown.countDown()完毕,再执行
                System.out.println(Thread.currentThread().getName() + " 子线程工作完毕...");
                await.countDown();  //子线程执行完毕,计数器减去一
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
运行结果:

主线程开始工作...
当前countDown的值为:1
当前countDown的值为:0
当前await的值为:5
主线程开始等待...
Thread-3 子线程工作完毕...
Thread-2 子线程工作完毕...
Thread-1 子线程工作完毕...
Thread-0 子线程工作完毕...
Thread-4 子线程工作完毕...
当前await的值为:0
所有子线程线程执行完毕,主线程继续执行!

小伙伴们可以自己运行程序试一试。

希望可以帮助小伙伴们更好的理解 CountDownLatch的作用。

你可能感兴趣的:(java)