CountDownLatch用于通知计算完成

 CountDownLatch是JDK提供的一个同步工具,它可以让一个或多个线程等待,一直等到其他线程中执行完成一组操作

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

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

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

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

常见案例:

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

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

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

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

主要有countDown方法和await方法,CountDownLatch在初始化时,需要指定用给定一个整数作为计数器。当调用countDown方法时,计数器会被减1;当调用await方法时,如果计数器大于0时,线程会被阻塞,一直到计数器被countDown方法减到0时,线程才会继续执行。计数器是无法重置的,当计数器被减到0时,调用await方法都会直接返回

调用countDown的线程不会阻塞,不需要等待计数器被减到0,只是调用await方法的线程需要等待

比如张三、李四和王五几个人约好去饭店一起去吃饭,这几个人都是比较绅士,要等到所有人都到齐以后才让服务员上菜。这种场景就可以用到CountDownLatch。

张三、李四和王五的顾客类:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class Customer implements Runnable {
    private CountDownLatch latch;
    private String name;

    public Customer(CountDownLatch latch, String name) {
        this.latch = latch;
        this.name = name;
    }

    @Override
    public void run() {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
            Random random = new Random();

            System.out.println(sdf.format(new Date()) + " " + name + "出发去饭店");
            Thread.sleep((long) (random.nextDouble() * 3000) + 1000);
            System.out.println(sdf.format(new Date()) + " " + name + "到了饭店");
            latch.countDown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这是服务员类:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

public class Waitress implements Runnable {
    private CountDownLatch latch;
    private String name;

    public Waitress(CountDownLatch latch, String name) {
        this.latch = latch;
        this.name = name;
    }

    @Override
    public void run() {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
            System.out.println(sdf.format(new Date()) + " " + name  + "等待顾客");
            latch.await();
            System.out.println(sdf.format(new Date()) + " " + name  + "开始上菜");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
再写一个测试类,用于模拟上面所说的场景:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class CountDownLatchTester {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);

        List<Thread> threads = new ArrayList<>(3);
        threads.add(new Thread(new Customer(latch, "张三")));
        threads.add(new Thread(new Customer(latch, "李四")));
        threads.add(new Thread(new Customer(latch, "王五")));
        for (Thread thread : threads) {
            thread.start();
        }

        Thread.sleep(100);
        new Thread(new Waitress(latch, "♥小芳♥")).start();

        for (Thread thread : threads) {
            thread.join();
        }
    }
}
运行以后的结果应该是这样的:

15:25:53.015 王五出发去饭店
15:25:53.015 李四出发去饭店
15:25:53.015 张三出发去饭店
15:25:53.062 ♥小芳♥等待顾客
15:25:54.341 张三到了饭店
15:25:54.358 李四到了饭店
15:25:56.784 王五到了饭店
15:25:56.784 ♥小芳♥开始上菜
 

可以看到,服务员小芳在调用await方法时一直阻塞着,一直等到三个顾客都调用了countDown方法才继续执行

具体参考:

腾讯面试居然跟我扯了半小时的CountDownLatch_万猫学社的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值