zoukankan      html  css  js  c++  java
  • Java并发包之CountDownLatch用法

    CountDownLatch计数器闭锁是一个能阻塞主线程,让其他线程满足特定条件下主线程再继续执行的线程同步工具。

    Latch闭锁的意思,是一种同步的工具类。类似于一扇门:在闭锁到达结束状态之前,这扇门一直是关闭着的,不允许任何线程通过,当到达结束状态时,这扇门会打开并允许所有的线程通过。且当门打开了,就永远保持打开状态。

    CountDowmLatch是一种灵活的闭锁实现,包含一个计数器,该计算器初始化为一个正数,表示需要等待事件的数量。countDown方法递减计数器,表示有一个事件发生,而await方法等待计数器到达0,表示所有需要等待的事情都已经完成。

    这句话的意思是:在单独主线程的情况下,创建多个子线程, 在保证主线程同步的情况下,同时又让多个子线程处理,可以使用 CountDownLatch来阻塞主线程,等待子线程执行完成,主线程才执行后续操作.

    常见案例:

    1:多线程读取批量文件, 并且读取完成之后汇总处理

    2:多线程读取Excel多个sheet,读取完成之后获取汇总获取的结果

    3:多个人一起一起来吃饭,主人等待客人到来,客人一个个从不同地方来到饭店,主人需要等到所有人都到来之后,才能开饭

    4:汽车站,所有乘客都从不同的地方赶到汽车站,必须等到所有乘客都到了,汽车才会出发,如果设置了超时等待,那么当某个时间点到了,汽车也出发

    作用:可以用来确保某些活动直到其他活动都完成后才继续执行。

    注意事项:

    使用CountDownLatch必须确保计数器数量与子线程数量一致,且countDown必须要执行,否则出现计数器不为0,导致主线程一致等待的情况

    在执行任务的线程中,使用了try...finally结构,该结构可以保证创建的线程发生异常时CountDownLatch.countDown()方法也会执行,也就保证了主线程不会一直处于等待状态。

    CountDownLatch非常适合于对任务进行拆分,使其并行执行,比如某个任务执行2s,其对数据的请求可以分为五个部分,那么就可以将这个任务拆分为5个子任务,分别交由五个线程执行,执行完成之后再由主线程进行汇总,此时,总的执行时间将决定于执行最慢的任务,平均来看,还是大大减少了总的执行时间。

    具体代码示例:

    模拟乘客登机的场景

    package com.puppy.demo;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    //刘小品
    public class CountDownLatchTest {
    
        public static void main(String[] args) throws InterruptedException {
    
            System.out.println("南京禄口机场_机长正在等待所有乘客登机");
            //CountDownLatch的计数器数量必须与线程的数量一致,否则可能出现一直等待的情况,即计数器不为0的情况
            //使用CountDownLatch 需要注意,子线程中的countDown()最好放到finnally里面,防止计数器不为0
            CountDownLatch latch = new CountDownLatch(3);
    
            ExecutorService ex = Executors.newCachedThreadPool();
            ex.execute(new ThreadTest1(latch));
            ex.execute(new ThreadTest2(latch));
            ex.execute(new ThreadTest3(latch));
            //等待所有乘客来机场
            System.out.println("所有乘客都在赶飞机的路上");
    
            //latch.await(1,TimeUnit.SECONDS);//模拟超时等待的情况
            latch.await(); //模拟等待的情况,不考虑子线程的处理实际
            System.out.println("南京禄口机场_机长启动飞机起飞");
            ex.shutdown();
        }
    
    }
    
    class ThreadTest1 extends Thread {
    
        CountDownLatch lanch;
    
        public ThreadTest1() {
    
        }
    
        public ThreadTest1(CountDownLatch lanch) {
            this.lanch = lanch;
        }
    
        @Override
        public void run() {
            try {
                Thread.sleep(2000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("正在马鞍山,准备赶到南京坐飞机,需要1小时的车程到机场");
            lanch.countDown();
        }
    }
    
    class ThreadTest2 extends Thread {
    
        CountDownLatch lanch;
    
        public ThreadTest2() {
    
        }
    
        public ThreadTest2(CountDownLatch lanch) {
            this.lanch = lanch;
        }
    
        @Override
        public void run() {
            System.out.println("正在徐州,准备赶到南京坐飞机,需要5小时的车程到机场");
            lanch.countDown();
        }
    }
    
    class ThreadTest3 extends Thread {
        CountDownLatch lanch;
    
        public ThreadTest3() {
    
        }
    
        public ThreadTest3(CountDownLatch lanch) {
            this.lanch = lanch;
        }
    
        @Override
        public void run() {
            System.out.println("正在芜湖,准备赶到南京坐飞机,需要2小时的车程到机场");
            lanch.countDown();
        }
    }

    执行结果

    latch.await()

    南京禄口机场_机长正在等待所有乘客登机
    所有乘客都在赶飞机的路上
    正在徐州,准备赶到南京坐飞机,需要5小时的车程到机场
    正在芜湖,准备赶到南京坐飞机,需要2小时的车程到机场
    正在马鞍山,准备赶到南京坐飞机,需要1小时的车程到机场
    南京禄口机场_机长启动飞机起飞
    

     

    超时等待的情况:latch.await(1,TimeUnit.SECONDS)

    主线程已经执行完成,但是子线程才结束,latch.await(1,TimeUnit.SECONDS)方法

    南京禄口机场_机长正在等待所有乘客登机
    所有乘客都在赶飞机的路上
    正在徐州,准备赶到南京坐飞机,需要5小时的车程到机场
    正在芜湖,准备赶到南京坐飞机,需要2小时的车程到机场
    南京禄口机场_机长启动飞机起飞
    正在马鞍山,准备赶到南京坐飞机,需要1小时的车程到机场
    

      

    
    
  • 相关阅读:
    606. Construct String from Binary Tree
    696. Count Binary Substrings
    POJ 3255 Roadblocks (次短路)
    POJ 2823 Sliding Window (单调队列)
    POJ 1704 Georgia and Bob (博弈)
    UVa 1663 Purifying Machine (二分匹配)
    UVa 10801 Lift Hopping (Dijkstra)
    POJ 3281 Dining (网络流之最大流)
    UVa 11100 The Trip, 2007 (题意+贪心)
    UVaLive 4254 Processor (二分+优先队列)
  • 原文地址:https://www.cnblogs.com/lewisat/p/11057901.html
Copyright © 2011-2022 走看看