Java并发编程之CountDownLatch

标题链接
SemaphoreJava并发编程之Semaphore.

一、概念

CountDownLatch简单理解为一个线程间的倒计时工具,可以使一个线程A在等待另外的一些子线程(B、C、D…)完成各自的工作后,A再进行工作。每当一个子线程执行完毕时,计数器就会减一,当计数器减为0时,主线程A再开始执行。

二、用法

1、一等多

某一个线程开始阻塞,直至其他n个线程执行完毕,再唤醒。
常用于多线程批量计算,多个线程计算的结果集统一插入数据库(计算过程中要考虑所用工具是否有并发问题)。

//初始化一个为n的计数器
countDownLatch cdl = new CountDownLatch(n);

//主线程等待
cdl.await();

//每个线程执行完毕时,计数器就减1
cdl.countDown();//-1
cdl.countDown();//-1
cdl.countDown();//-1
...
//当计数器变为0时,即减了n次,在await()的线程就会被唤醒

2、多等一

强调的是多个线程在同一时刻开始执行,多await(),一countDown()。

//初始化一个计数器为1的对象
CountDownLatch cdl = new CountDownLatch(1);

//多个线程进行等待
cdl.await();
cdl.await();
cdl.await();
...

//主线程减1,唤醒在等待中的线程继续执行。
cdl.countDown();

三、示例

1、一等多

/**
 * @author chengyanqi
 * @date 2020/7/13 22:34
 */
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(5);//计数器
        for (int i = 0; i < 5; i++) {
            int finalI = i;
            Runnable runnable = () -> {
                System.out.println("子线程:" + Thread.currentThread().getName() + "开始执行");
                try {
                    Thread.sleep(finalI * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                cdl.countDown();//-1
                System.out.println("子线程:" + Thread.currentThread().getName() + "执行完毕,当前计数器中的个数:" + cdl.getCount());
            };
            Thread thread = new Thread(runnable, "Thread" + i);
            thread.start();
        }
        System.out.println("主线程进入等待,等待子线程执行完毕...");
        cdl.await();//等待
        System.out.println("所有线程执行完毕,主线程开始执行...当前计数器中的个数:" + cdl.getCount());
    }
}
子线程:Thread0开始执行
主线程进入等待,等待子线程执行完毕...
子线程:Thread2开始执行
子线程:Thread4开始执行
子线程:Thread3开始执行
子线程:Thread1开始执行
子线程:Thread0执行完毕,当前计数器中的个数:4
子线程:Thread1执行完毕,当前计数器中的个数:3
子线程:Thread2执行完毕,当前计数器中的个数:2
子线程:Thread3执行完毕,当前计数器中的个数:1
子线程:Thread4执行完毕,当前计数器中的个数:0
所有线程执行完毕,主线程开始执行...当前计数器中的个数:0

2、多等一

/**
 * @author chengyanqi
 * @date 2020/7/13 22:47
 */
public class CountDownLatchDemo2 {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        for (int i = 0; i < 5; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName() + "准备就绪");
                        countDownLatch.await();//所有线程等待中
                        System.out.println(Thread.currentThread().getName() + "开始执行");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            new Thread(runnable, "Thread" + i).start();//开启线程
        }
        Thread.sleep(1000);
        System.out.println("所有线程准备就绪");
        for (int i = 5; i > 0; i--) {
            System.out.println(i + "秒后开始执行...");
            Thread.sleep(1000);
        }
        countDownLatch.countDown();//-1
        System.out.println("所有线程开始执行!");
    }
}

Thread0准备就绪
Thread2准备就绪
Thread3准备就绪
Thread1准备就绪
Thread4准备就绪
所有线程准备就绪
5秒后开始执行...
4秒后开始执行...
3秒后开始执行...
2秒后开始执行...
1秒后开始执行...
所有线程开始执行!
Thread0开始执行
Thread3开始执行
Thread2开始执行
Thread4开始执行
Thread1开始执行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程大帅气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值