• Java CountDownLatch 学习总结


    来源包

    同为 java.util.concurrent 下的,即也是并发多线程相关下的类,直译 “倒计时锁存器”,一般用于多线程场景,单一的线程也可以,用于等待多个任务完成后再执行其他操作;

    提供方法

    await()

    导致当前线程等待,直到锁存器倒数到零,除非该线程是{@linkplain Thread35;interrupt interrupted}即被打断状态。
    如果当前计数为零,则此方法立即返回。
    如果当前计数大于零,则当前线程将出于线程调度目的被禁用,并处于休眠状态,直到发生以下两种情况之一:
    由于调用{@link#countDown}方法,计数达到零;或者其他线程{@linkplain thread#中断}当前线程。
    如果当前线程:
    在进入此方法时设置了其中断状态;或者
    在等待时{@linkplain Thread#interrupt interrupted},
    则抛出{@link InterruptedException},并清除当前线程的中断状态。

    简单说就是当使用了这个方法后当前这一个线程将进入等待状态,直到计数器被减到0或者当前线程被中断,计数器被减到0后,所有等待的线程将被唤醒继续向下执行

    await(long timeout, TimeUnit unit)

    同上,但是指定了等待的超时时间,即线程除了上方两种被唤醒的情况下,等待到超时时间后也会被唤醒

    countDown()

    当前计数器减一,如果如果减到 0 则唤醒所有等待在这个 CountDownLatch 上的线程。

    getCount()

    获取当前计数的数值

    业务书写示例

    将需要一会儿处理的业务 list 设置为计数器的大小,
    然后对里面的业务数据执行异步操作,处理业务过程中不论是否有异常都需要对计数器减一,最终使用 await 等待所有任务执行完成,执行完成后,将进入后续处理

                final CountDownLatch latch = new CountDownLatch(lists.size());
                
                for (List<JSONObject> item: lists) {
                    executor.submit(new Runnable() {
                        @Override
                        public void run() {
                            // ....... 业务处理
                            } catch (Exception e) {
                                // 异常处理
                            } finally {
                                latch.countDown();
                            }
                        }
                    });
                }
    
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    log.error("线程被中断", e);
                }
    
           // lists 处理完成后的其他业务操作
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    一般代码示例

    public static void main(String[] args) throws InterruptedException {
            final CountDownLatch downLatch = new CountDownLatch(3);
    
            Await wait111 = new Await("wait111", downLatch);
            Await wait222 = new Await("wait222", downLatch);
            CountDownStart countDownStart = new CountDownStart(downLatch);
    
            wait111.start();
            wait222.start();
            Thread.sleep(1000);
            countDownStart.run();
    
        }
    
    
    class Await extends Thread{
    
        private CountDownLatch countDownLatch;
        private String name;
    
        public Await(String name, CountDownLatch countDownLatch){
            this.name = name;
            this.countDownLatch = countDownLatch;
        }
    
    
        @Override
        public void run() {
            System.out.println(name + " start.....");
            System.out.println(name + " run.....");
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + " continue.....run");
        }
    }
    
    class CountDownStart extends Thread{
    
        private CountDownLatch countDownLatch;
    
        public CountDownStart(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }
    
        @Override
        public void run() {
            countDownLatch.countDown();
            countDownLatch.countDown();
            countDownLatch.countDown();
            System.out.println("start countDown");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    运行结果:

    wait222 start.....
    wait222 run.....
    wait111 start.....
    wait111 run.....
    start countDown
    wait111 continue.....run
    wait222 continue.....run
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    但是当我把线程等待去除后:

        public static void main(String[] args) throws InterruptedException {
            final CountDownLatch downLatch = new CountDownLatch(3);
    
            Await wait111 = new Await("wait111", downLatch);
            Await wait222 = new Await("wait222", downLatch);
            CountDownStart countDownStart = new CountDownStart(downLatch);
    
            wait111.start();
            wait222.start();
    //        Thread.sleep(1000);
            countDownStart.run();
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    结果:

    start countDown
    wait111 start.....
    wait111 run.....
    wait111 continue.....run
    wait222 start.....
    wait222 run.....
    wait222 continue.....run
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    另外两个线程线程并没有开始就执行,可能被抢占了,也可能调度优先度不同,实际使用时还是需要多多实验

  • 相关阅读:
    Fultter学习日志(2)-构建第一个flutter应用
    https协议
    新手指南|如何快速参与Moonbeam Ignite
    一次I/O操作的过程
    再获5G RedCap能力认证!宏电5G RedCap工业智能网关通过中国联通5G物联网OPENLAB开放实验室测试验证
    次轮Okaleido Tiger即将登录Binance NFT,引发社区热议
    挑战30天学完Python:Day2 夯实基础 - 布尔值和运算符
    自动驾驶感知算法面经(20+)
    tomcat双击启动startup.bat时出现闪退完美解决方法
    Worthington丨Worthington 磷酸酶,碱性
  • 原文地址:https://blog.csdn.net/weixin_44131922/article/details/126584977