java多线程--CountDownLatch闭锁的应用

前言:

        在开发过程中,可能会遇到这样一种情况。当要进行事件A,B。A的可执行前提是:B的某一部分必须先完成。这种时候,如果采用join的话,必须等到B执行完,A才能进行。从事件安全上来说虽然没有什么问题,但是,从效率上来讲,显然是不能接受的。

       举个例子:小明和他女朋友小红,准备周末在家做一顿大餐。他们买了大虾、里脊和西兰花。小明帮忙洗菜(事件A)。小红掌勺(事件B)。小红要做菜的前提是:大虾、里脊和西兰花中的至少一种已经准备好。小红可以等到小明全部都洗完了,再开始做菜(可以用join来实现)。当然,如果大虾弄好了,小红可以马上开始做菜(CountDownLatch来实现),这样就更快了。而小明,可以在小红做菜的时候,继续,洗里脊和西兰花。

        

准备:

CountDownLatch在java.util.concurrent下提供。此次使用下面三个方法

   public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

count控制初始化线程的数量

public void countDown() {
        sync.releaseShared(1);
    }

此方法用来将计数器减一

public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

此方法当CountDownLatch中的计数器为0时才会执行


上测试代码

@Slf4j
public class ThreadTest {
    
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(1);
        XiaoMing xiaoMing = new XiaoMing(cdl);
        XiaoHong xiaoHong = new XiaoHong();

        log.info("做饭");
        xiaoMing.start();
        cdl.await();
        xiaoHong.start();
    }
}
@Slf4j
public class XiaoHong extends Thread {
    @Override
    public void run() {
        log.info("小红开始做菜");
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("小红做菜结束");
        log.info("开饭");
    }
}
@Slf4j
public class XiaoMing extends Thread {
    CountDownLatch cdl;
    XiaoMing(CountDownLatch cdl){
        this.cdl = cdl;
    }
    @Override
    public void run() {
        try {
            //处理具体业务逻辑
            log.info("小明开始处理:大虾");
            Thread.sleep(1000);
            log.info("小明将 大虾 处理完");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            cdl.countDown();
        }

        try {
            log.info("小明开始处理:里脊");
            Thread.sleep(1000);
            log.info("小明将 里脊 处理完");
            log.info("小明开始处理:西兰花");
            Thread.sleep(1000);
            log.info("小明将 西兰花 处理完");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

最终结果:


从测试结果我们可以看到,到小明处理完大虾以后,小红就开始做菜了。(小明开始处理里脊和小红开始做菜,会有交换的情况)。通过,这个例子相信可以,理解闭锁的灵活之处。


CountDownLatch 使用的注意点:

1、只有当count为0时,await之后的程序才够执行。

2、countDown必须写在finally中,防止发生异程常时,导致程序死锁。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值