CountDownLatch的用法,配图版

CountDownLatch 是线程协作中的并发流程控制的工具类,它能在多线程场景中,可以让多个线程执行完自己的任务后,在某个等待点集合,集合完毕后,再继续等待点后面的工作,如图

图上有5个蓝色的勇士,每个勇士需要到每扇门寻找钥匙后,就可以在关闭橙色公主的门前等待,直到所有勇士拿到所有钥匙,来开锁才能救出公主。救出公主的关键是必须有5把钥匙
CountDownLatch的用法,配图版_第1张图片

其中一勇士调用了 CounDownLatch.count() 拿到了锁

CountDownLatch的用法,配图版_第2张图片

勇士拿到锁后打开了一把锁

CountDownLatch的用法,配图版_第3张图片

其它勇士也陆续拿到锁并打开锁了

CountDownLatch的用法,配图版_第4张图片


CountDownLatch的用法,配图版_第5张图片

最终救出了公主,因为满足了CountDownLatch.await() 的条件

CountDownLatch的用法,配图版_第6张图片

5勇士救出了公主,这场景想想就觉得感动

CountDownLatch的用法,配图版_第7张图片

代码演示

public class CountDownLatchDemo {
     

    static CountDownLatch countDownLatch = new CountDownLatch(5);


    public static void main(String[] args) {
     

        for (int i = 1; i < 6; ++i) {
     
            new Thread(new Task(), "勇士" + i).start();
        }

        try {
     
            System.out.println("等待勇士的搭救...");
            countDownLatch.await();
        } catch (InterruptedException e) {
     
            e.printStackTrace();
        }

        System.out.println("勇士都到达,锁已全部打开,成功救出了公主,感动!!");

    }

    static class Task implements Runnable {
     

        @Override
        public void run() {
     
            System.out.println(Thread.currentThread().getName() + "拿到了钥匙");
            countDownLatch.countDown();
            System.out.println(Thread.currentThread().getName() + "开了锁");
        }
    }
}

CountDownLatch的用法,配图版_第8张图片
上面的图所说的,拿到锁,其实是调用 CountDownLatch.countDown(),使得 CountDownLatch 类中的 count 变量减1,count 的初始值是创建对象的时候,传进去的参数值。

当 count减为0的时候,就满足 CountDownLatch.await() 的条件,所有等待在这个点的任务,都会继续执行下去

构造器方法

CountDownLatch(int count) 

CountDownLatch类只提供了一个构造器,并没有其它构造器了,它所传入的参数,代表着你在到达 await()方法的地方的时候,其它地方需要调用多少次 countDown()方法的次数

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

从源码我们可以看到,传入的参数不能小于0,当小于0的时候,会抛出 IllegalArgumentException异常

等待方法

void await() throws InterruptedException 

boolean await(long timeout, TimeUnit unit)
        throws InterruptedException

第一个方法,当调用这个方法的时候,所有线程都会阻塞在这个点,当其它操作触及调用 countDown()方法,使得 count为0的时候,其它阻塞在这里的任务都会继续执行下去

第二个方法,在上面的基础上,加上了超时时间,这里的是等待其它任务在规定超时时间调用 countDown(),如果没有在超时时间内调用,则不阻塞其任务,直接放行任务,让任务继续执行下去

获取当前 count的数量

long getCount()

调用这个方法,可以知道现在count的值,从而知道还需要调用多少次 countDown()方法,从能满足 await()的条件

释放门闩

void countDown()

调用这个方法,可以让 count减1


:当 count的值为0的时候,这时候无论有多少个任务执行到这个地方,都不会被阻塞了,因为 CountDownLatch只能用一次,而它的 count的值,不能被重置,跟 CyclicBarrier 有所区别


欢迎大家关注下个人的「公众号」:独醉贪欢

你可能感兴趣的:(Java并发编程,Java,并发编程,CountDownLatch)