铁锤的IT奇妙探险 Java Back-End Coder

简单介绍CountDownLatch

2020-07-13


CountDownLatch是 JDK 提供的并发流程控制的工具类,它是在 java.util.concurrent 包下,在 JDK1.5 以后加入的。

CountDownLatch

它是 JDK 提供的并发流程控制的工具类,它是在 java.util.concurrent 包下

最开始 CountDownLatch 设置的初始值为 3,然后 T0 线程上来就调用 await 方法,它的作用是让这个线程开始等待,等待后面的 T1、T2、T3,它们每一次调用 countDown 方法,3 这个数值就会减 1,也就是从 3 减到 2,从 2 减到 1,从 1 减到 0,一旦减到 0 之后,这个 T0 就相当于达到了自己触发继续运行的条件,于是它就恢复运行了。

主要方法

  1. 它的构造函数需要传入一个参数,该参数 count 是需要倒数的数值。
  2. await():调用await()方法的线程开始等待,直到count值为0的时候才会继续执行。
  3. await()有一个重载的方法,里面会传入超时参数,如果超时就不再等待了。
  4. countDown():把数值倒数 1,也就是将 count 值减 1,直到减为 0 时,且之前等待的线程会被唤起

用法

场景一

一个线程等待其他多个线程都执行完毕,再继续自己的工作。比如在比赛跑步时有5个运动员参赛,终点有一个裁判员,当所有人都跑到终点之后,相当于裁判员等待5个运动员都跑到终点,宣布比赛结束。

public class RunDemo1 {
	public static void main(String[] args) throws InterruptedException {
		CountDownLatch latch = new CountDownLatch(5);
		ExecutorService service = Executors.newFixedThreadPool(5);
		for (int i = 0; i < 5; i++) {
		    final int no = i			//新建任务
		    Runnable runnable = new Runnable() {
		        @Override
		        public void run() {
		            try {
		                Thread.sleep((long) (Math.random() * 10000));
		                System.out.println		运动员完成了比赛");
		            } catch (InterruptedException e) {
		                e.printStackTrace();
		            } finally {
		                latch.countDown();
		            }
		        }
		 			//提交任务
		    service.submit(runnable);
		}
		System.out.println("等待5个运动员都跑完.....");

		//调用await让主线程开始等待子线程执行完毕
        latch.await();
        System.out.println("所有人都跑完了比赛结束。");
    }
}

我们新建了一个初始值为 5 的 CountDownLatch,然后建立了一个固定 5 线程的线程池,用一个 for 循环往这个线程池中提交 5 个任务,每个任务代表一个运动员,这个运动员会首先随机等待一段时间,代表他在跑步,然后打印出他完成了比赛,在跑完了之后,同样会调用 countDown 方法来把计数减 1。

场景二

多个线程等待某一个线程的信号,同时开始执行。比如在运动员起跑之前都会等待裁判员发号施令,一声令下运动员统一起跑。

public class RunDemo2 {
	public static void main(String[] args)	throws InterruptedException {
	    System.out.println("运动员有5秒的准备时间");
	    CountDownLatch countDownLatch = new CountDownLatch(1);
	    ExecutorService service = Executors.newFixedThreadPool(5);
	    for (int i = 0; i < 5; i++) {
	        final int no = i + 1;
	        Runnable runnable = new Runnable() {
	            @Override
	            public void run() {
	                System.out.println(	 "号运动员准备完毕,等待裁判员的发令枪");
	                try						//五个线程都会进入等待状态
	                    countDownLatch.await();
	                    System.out.println(no + "号运动员开始跑步了");
	                } catch (InterruptedException e) {
	                    e.printStackTrace();
	                }
	            }
	        };
	        service.submit(runnable);
	    }
	    Thread.sleep(5000);
	    System.out.println("5秒准备时间已过,发令枪响,比赛开始!"		//调用countDown之后才会将五个等待的线程唤		然后线程执行await()方法之后的逻辑
	    countDownLatch.countDown();
	}
}

Similar Posts

上一篇 JVM入门

下一篇 Future解析

Comments