Java随笔-CountDownLatch

概述

CountDownLatch其实就是一个计数器,用来同步一个或多个任务,强制任务按步骤执行,多用来协调多线程。也就是一个任务想要执行,必须要等其他任务执行完后才能执行。
CountDownLatch需要设置任务初始值,也就是需要执行的任务需要分几步执行,初始值就设为几,当计数值不为0的时候,任何一个对象调用wait()都将被阻塞,每一个步骤执行完毕后,调用countDown()计数都会减一。
调用countDown()的任务在调用时没有被阻塞,只有调用wait()才会被阻塞,一直到计数值为0。
该思想并非只在并发中使用,实际开发中很多场景也会使用相似的方法。

使用

方法解读

CountDownLatch非常简单,只有几个方法。
在这里插入图片描述

  • await(), 等待计数器的值为0,若为0就返回,如果不为0就阻塞。
  • await(long timeout, TimeUnit unit),在指定时间内等待计数器的值为0,若为0,则返回true,若不为0,则返回false。
  • countDown(),计数减1,若减1之前为1,则置为0,且唤醒所有等待的线程;若减1之前为0,则啥也不做。
  • getCount(),获取当前计数的值。

使用

  1. 创建线程。
    产品经理:
public class ProductManager extends Thread {
    private CountDownLatch countDown;

    public ProductManager(CountDownLatch countDown) {
        this.countDown = countDown;
    }

    @Override
    public void run() {
        if(countDown.getCount() != 4){
            try {
                countDown.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("俺是产品经理,俺是提需求的");
        countDown.countDown();
    }
}

UI设计:

public class UI extends Thread {
    private CountDownLatch countDown;

    public UI(CountDownLatch countDown) {
        this.countDown = countDown;
    }

    @Override
    public void run() {
        if(countDown.getCount() != 3){
            try {
                countDown.await(1000, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("俺是设计,俺是设计界面的");
        countDown.countDown();

    }
}

开发:

public class Developer extends Thread {
    private CountDownLatch countDown;

    public Developer(CountDownLatch countDown) {
        this.countDown = countDown;
    }

    @Override
    public void run() {
        if(countDown.getCount() != 2){
            try {
                countDown.await(2000, TimeUnit.MILLISECONDS);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("俺是开发,俺是干活的");
        countDown.countDown();
    }
}

测试:

public class Test extends Thread {
    private CountDownLatch countDown;

    public Test(CountDownLatch countDown) {
        this.countDown = countDown;
    }

    @Override
    public void run() {
        if(countDown.getCount() != 1){
            try {
                countDown.await(3000, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("俺是测试,俺是保证产品质量的");
        countDown.countDown();

    }
}
  1. 按指定步骤执行。
    public static void main(String[] args) {

        CountDownLatch countDownLatch = new CountDownLatch(4);
        // UI设计
        UI ui = new UI(countDownLatch);
        ui.start();
        // 产品经理
        ProductManager productManager = new ProductManager(countDownLatch);
        productManager.start();
        // 开发
        Developer developer = new Developer(countDownLatch);
        developer.start();
        // 测试
        Test test = new Test(countDownLatch);
        test.start();
        //
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("产品可以上线了");
    }
  1. 结果。
俺是产品经理,俺是提需求的
俺是设计,俺是设计界面的
俺是开发,俺是干活的
俺是测试,俺是保证产品质量的
产品可以上线了

总结

CountDownLatch强调是其他任务执行完后,再执行指定任务,其他任务的执行顺序无法保证,当然可以多用几个CountDownLatch,也可以使用join()。
join可以保证线程按顺序执行,即使线程睡眠。

      try {
            productManager.start();
            productManager.join();
            ui.start();
            ui.join();
            developer.start();
            developer.join();
            test.start();
            test.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

执行结果是一样的。
CountDownLatch中线程睡眠,执行顺序就不一样了。
ProductManager 睡眠1000ms。

public class ProductManager extends Thread {
    private CountDownLatch countDown;

    public ProductManager(CountDownLatch countDown) {
        this.countDown = countDown;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("俺是产品经理,俺是提需求的");
        countDown.countDown();
    }
}

Developer睡眠3000ms。
执行:

        CountDownLatch countDownLatch = new CountDownLatch(4);
        // UI设计
        UI ui = new UI(countDownLatch);
        // 产品经理
        ProductManager productManager = new ProductManager(countDownLatch);
        // 开发
        Developer developer = new Developer(countDownLatch);
        // 测试
        Test test = new Test(countDownLatch);

        productManager.start();
        ui.start();
        developer.start();
        test.start();
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("产品可以上线了");

结果:

俺是设计,俺是设计界面的
俺是测试,俺是保证产品质量的
俺是产品经理,俺是提需求的
俺是开发,俺是干活的
产品可以上线了

CountDownLatch只能是只触发一次的事件。若是需要多次触发,就需要使用CyclicBarrier。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值