CountDownLatch多任务处理利器

本文介绍Java并发包中CountDownLatch的使用方法,通过电影院场景演示如何让主线程等待多个子线程完成任务。并展示了如何设置超时时间,即使未达到预定条件也能继续执行。

CountDownLatch 是由java并发包提供的一个同步计数器,从字面意义上去理解可以分成两部分CountDown 和 Latch,CountDown就是计数的意思,Latch是门闩,这个同步工具就是通过保证多线程环境下,通过门闩限制主线程执行,子线程执行后计数减1,直到减为0,门闩打开,主线程执行。

场景一:主任务等待其它子任务完成后再执行。

背景:电影院等待所有人都到齐了还开始播放电影,有一个电影院的类为主线程,看电影的人为子线程,假设电影院能容纳5人看电影,下面的类将利用CountDownLatch实现该功能。

public class Cinema {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for(int i=0; i<5; i++){
            executor.execute(new Person(countDownLatch));
        }

        System.out.println("电影院等待人入场...");
        //阻塞当前线程,直到计数器的值为0
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("人已到齐,开始播放电影...");
    }
}
public class Person implements Runnable{
    private CountDownLatch countDownLatch;
    public Person(CountDownLatch countDownLatch){
        this.countDownLatch = countDownLatch;
    }


    @Override
    public void run() {
        try {
            Thread.sleep((long) (Math.random() * 0));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(String.format("%s又有观众入场了", Thread.currentThread().getId()));
        countDownLatch.countDown();
        System.out.println(String.format("%s还有%s人未入场", Thread.currentThread().getId(), countDownLatch.getCount()));
    }
}

执行下看结果:

电影院等待人入场...
13又有观众入场了
11又有观众入场了
12又有观众入场了
11还有3人未入场
13还有4人未入场
12还有2人未入场
13又有观众入场了
11又有观众入场了
13还有1人未入场
人已到齐,开始播放电影...
11还有0人未入场

这个时候可以思考一下现实情况,不是任何时候电影院都是满场才放电影的,那么就需要设置一个时间,如果到时间了人还未到齐,就开始播放电影,这个程序怎么写呢。

public class Cinema {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for(int i=0; i<5; i++){
            executor.execute(new Person(countDownLatch));
        }

        System.out.println("电影院等待人入场...");
        //阻塞当前线程,直到计数器的值为0
        try {
            countDownLatch.await(300, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("人已到齐,开始播放电影...");
    }
}

这里用了CountDownLatch的await的另外一个重载方法,并且增加了CountDownLatch的阈值,让人更多一些方便跑数据。看结果:

电影院等待人入场...
12又有观众入场了
13又有观众入场了
13还有8人未入场
12还有9人未入场
11又有观众入场了
11还有7人未入场
12又有观众入场了
12还有6人未入场
13又有观众入场了
13还有5人未入场
人已到齐,开始播放电影...

发现还有5人未到场的时候,电影就开始播放了,是不是很赞。现在大家是不是对CountDownLatch的使用得心应手了,在这里需要提醒的是多线程环境下一定要注意异常,如果发生了异常该如何保证数据一致性,主线程是否要做回滚处理。我们在利用多线程实现性能提升的时候,必然会有线程安全的问题。

评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值