zoukankan      html  css  js  c++  java
  • java并发编程(八)----(JUC)CountDownLatch

    CountDownLatch 是一个非常实用的多线程控制工具类。” Count Down ” 在英文中意为倒计数, Latch 为门问的意思。如果翻译成为倒计数门阀, 我想大家都会觉得不知所云吧! 因此,这里简单地称之为倒计数器。在这里, 门问的含义是:把门锁起来,不让里面的线程跑出来。因此,这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束, 再开始执行。

    CountDown Latch 的构造函数接收一个整数作为参数,即当前这个计数器的计数个数。

    public CountDownLatch(int count)

    CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。一个CountDownLatch初始化为给定的计数 。 调用await方法阻塞,直到当前计数为零,在调用countDown()方法之后,所有等待的线程被释放,任何后续调用await立即返回。 这是一次性的现象 - 计数不能重置。 如果需要重置计数,考虑使用CyclicBarrier ,CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。

    主要方法:

    // 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
    void await()
    // 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
    boolean await(long timeout, TimeUnit unit)
    // 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
    void countDown()
    // 返回当前计数。
    long getCount()

    我们来看一个例子:

    public class TestCountDownLatch {
        private static final int RUNNER_NUMBER = 5; // 运动员个数
        private static final Random RANDOM = new Random();
        public static void main(String[] args) {
            // 用于判断发令之前运动员是否已经完全进入准备状态,需要等待5个运动员,所以参数为5
            CountDownLatch readyLatch = new CountDownLatch(RUNNER_NUMBER);
            // 用于判断裁判是否已经发令,只需要等待一个裁判,所以参数为1
            CountDownLatch startLatch = new CountDownLatch(1);
            for (int i = 0; i < RUNNER_NUMBER; i++) {
                Thread t = new Thread(new Runner((i + 1) + "号运动员", readyLatch, startLatch));
                t.start();
            }
            try {
                readyLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            startLatch.countDown();
            System.out.println("裁判:所有运动员准备完毕,开始...");
        }
        static class Runner implements Runnable {
            private CountDownLatch readyLatch;
            private CountDownLatch startLatch;
            private String name;
            public Runner(String name, CountDownLatch readyLatch, CountDownLatch startLatch) {
                this.name = name;
                this.readyLatch = readyLatch;
                this.startLatch = startLatch;
            }
            public void run() {
                int readyTime = RANDOM.nextInt(1000);
                System.out.println(name + ":我需要" + readyTime + "秒时间准备.");
                try {
                    Thread.sleep(readyTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(name + ":我已经准备完毕.");
                readyLatch.countDown();
                try {
                    startLatch.await();  // 等待裁判发开始命令
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(name + ":开跑...");
            }
        }
    }

    打印结果:

    1号运动员:我需要547秒时间准备.
    2号运动员:我需要281秒时间准备.
    4号运动员:我需要563秒时间准备.
    5号运动员:我需要916秒时间准备.
    3号运动员:我需要461秒时间准备.
    2号运动员:我已经准备完毕.
    3号运动员:我已经准备完毕.
    1号运动员:我已经准备完毕.
    4号运动员:我已经准备完毕.
    5号运动员:我已经准备完毕.
    裁判:所有运动员准备完毕,开始...
    3号运动员:开跑...
    2号运动员:开跑...
    1号运动员:开跑...
    4号运动员:开跑...
    5号运动员:开跑...
    
    Process finished with exit code 0

    注意:计数器必须大于等于0,只是等于0时候,计数器就是零,调用await方法时不会阻塞当前线程。

  • 相关阅读:
    获得ip地理信息的几种方法
    设置 phoneGap/Cordova 3.4 应用程序启动动画闪屏 SplashScreen
    backbone实例01
    即使世界明天毁灭,我今天也要种下葡萄树
    真言真语
    美文美句
    25个实用的jQuery技巧和解决方案
    突袭HTML5之WebGL 3D概述
    敏捷开发之Scrum扫盲篇
    javascript中undefined和null的区别详解
  • 原文地址:https://www.cnblogs.com/rickiyang/p/11074262.html
Copyright © 2011-2022 走看看