CountDownLatch 使用

Posted song27

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CountDownLatch 使用相关的知识,希望对你有一定的参考价值。

    CountDownLatch 是一种同步辅助工具, 它允许一个或多个线程等待 直到其它线程的一组操作完成。JDK 1.5加入 。

   给定count可以获取CountDownLatch对象。类似于一种记数器,通过getCount()可获知还有多少线程没有执行完成。调用await()方法表示进入阻塞,直到count变成0, 程序方可执行下去。

 技术图片

  主线程Tm,调用具体执行业务内容的异步线程组(T0,T1,T2,T3),接下来调用await()方法,让主线程进行等待中。 当前count=4。 异步线程组中的每个线程执行完成后,都 会调用countDown(),表示对count进行减1操作。当四个线程全部执行完成,count==0,则主线程Tm继续往下执行。

 

  构造函数:CountDownLatch latch = new CountDownLatch(count)

 

  需要注意的是,初始化CountDownLatch时的count必需与异步线程组的线程数保持一致,线程数多或少于count,会出现永远等待或业务没有执行完成主线程就往下执行了。

 

  主要的应用场景: 一个业务分多步骤,每个步骤中又分多个并行子模块,子模块全部完成才能进行到下一步。 比如,一张综合性报表是由几张小报表汇总而成,必需要先执行完所有的小报表,方可执行综合性报表汇总。

 

  核心方法:

 

  countDown(): 减少计数, 如果计数为0,则释放所有的等待线程。  如果计数大于0,则进行计数减1; 如果计数=0,则什么都不会发生。

 

  await():线程阻塞。1、计数count=0,2、线程发生interrupt异常。 如果计数=0,则方法立即返回。

 

  await(long timeout, TimeUnit unit):线程阻塞。1、计数count=0;2、线程发生interrupt异常;3、等待超时。

 

 

 

  代码实现:

第一种:

 

 

public void run1(){
        LocalDateTime beginTime = LocalDateTime.now();
        Thread[] threads = new Thread[10];
        CountDownLatch latch = new CountDownLatch(threads.length);

        for (int i=0;i<threads.length;i++){
            threads[i] = new Thread(()->{

                /**
                 * 执行业务流程
                 */
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch.countDown();
                System.out.println(LocalDateTime.now()+"==="+Thread.currentThread().getName());
            },"t"+i);
        }

        for (Thread t : threads){
            t.start();
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(beginTime+"---------end latch>>>>"+LocalDateTime.now());
    }

 

 

第二种:使用线程池

public void run2()  {
        LocalDateTime beginTime = LocalDateTime.now();
        int threadCount = 10 ;
        CountDownLatch doneLatch = new CountDownLatch(threadCount);
        Executor executor = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < threadCount; i++) {
            executor.execute(new WorkRunnable(doneLatch, i));
        }

        try {
            doneLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(beginTime+"---------end latch>>>>"+LocalDateTime.now());
    }


class WorkRunnable implements  Runnable {

    private CountDownLatch latch ;
    private int index;

    public WorkRunnable(CountDownLatch latch, int index){
        this.latch = latch;
        this.index = index;
    }

    @Override
    public void run() {

        /**
         * 执行业务流程
         */
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        latch.countDown();
        System.out.println(LocalDateTime.now()+"  =>  "+index);
    }
}

 

以上是关于CountDownLatch 使用的主要内容,如果未能解决你的问题,请参考以下文章

使用CountDownLatch模拟线程并发执行代码

Java并发多线程编程——CountDownLatch

CountDownLatch如何使用?

代码优化:CompletableFuture + countDownLatch + Vector

代码优化:CompletableFuture + countDownLatch + Vector

JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch(使用CountdownLatch原理改进: 配合线程池使用)