• Java CountDownLatch的使用方法


    摘要:介绍Java中CountDownLatch的使用方法,重点包括计数器的值、countDown和await。计数器的值表示任务线程的个数,每次countDown都会使计数减一,减到0的时候调用await方法的线程就不再被阻塞。

    综述

      CountDownLatch一般被称作"计数器",计数器的初始值是线程的数量,是一个同步工具类,用来协调多个线程之间的同步。其中,count down是倒数的意思,latch则是门闩的含义,整体含义可以理解为倒数的门栓;有一点“三二一,芝麻开门”的感觉。

      CountDownLatch在初始化时,需要指定一个正整数作为计数器起始值,每当一个线程执行完毕后,计数器就被countDown方法减1,当计数器为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就被唤醒,恢复工作。从线程执行状态的角度分析,就是允许一个或多个线程等待,直到其它线程执行完成才继续往下走。

      CountDownLatch是在java 1.5 被引入的,与它一起被引入的工具类还包括CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue等,它们都位于java.util.cucurrent包下。

      CountDownLatch的计数器无法被重置,当计数器被减到0时,调用await方法会直接返回。这一点有别于Semaphore,Semaphore是可以通过release操作恢复信号量的。

    CountDownLatch类

      CountDownLatch 类提供了三个核心构造器:

    //参数count为计数值,即线程个数
    public CountDownLatch(int count) {  };  
        /**
         * Causes the current thread to wait until the latch has counted down to
         * zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
         *
         * <p>If the current count is zero then this method returns immediately.
         *
         * 调用await()方法的线程会被挂起,直到count值为0才继续执行
         */
    public void await() throws InterruptedException { };   
    //和await()类似,只不过等待一定的时间后,如果计数器的值还没倒数至0,就会被唤醒继续执行
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  
        /**
         * Decrements the count of the latch, releasing all waiting threads if
         * the count reaches zero.
         * 每次减少一个门闩数,如果等于零,则释放等待线程
         * <p>If the current count is greater than zero then it is decremented.
         * If the new count is zero then all waiting threads are re-enabled for
         * thread scheduling purposes.
         *
         * <p>If the current count equals zero then nothing happens.
         */
    public void countDown() { }; 
    

      如果想使线程处于等待状态,则调用await()方法,此线程一般是主线程。温馨提示,await()方法并没有规定只能由一个线程执行,如果多个线程同时执行await()方法,那么这几个线程都将处于等待状态,并且以共享模式享有同一把锁。另外,当同一个线程多次调用countDown()方法时,每次都会使计数器减一;

      简单总结一下,CountDownLatch有三个重点:计数器的值、await、countDown。计数器的值表示任务线程的个数,每次countDown都会使计数减一,减到0的时候await方法所在的线程就不再被阻塞。

    使用场景

      CountDownLatch非常适合于对任务进行拆分,使其并行执行,实现最大的并行性。某一线程A在开始运行前一直被阻塞,需等待n个其它线程执行完毕,则需将CountDownLatch的计数器初始化为 new CountDownLatch(n),每当一个任务线程执行完毕,则调用countDown()函数使得计数器减一;当计数器变为0时,在CountDownLatch上await()的线程A就会被唤醒。

      例1,会计汇总一年的财务报表时,可以把任务按照季度拆分为四份,那么就可以将这个大任务拆分为4个子任务,分别交由4个财务(线程)执行,执行完成之后再由主财务(主线程)进行财务汇总。此时,总的执行时间将决定于执行最慢的任务,通常来看,还是可以大大减少总的执行时间。

      假2,有10个线程需要加载一些资源,而另外一个线程A必须在所有资源被加载完成后才能继续执行,那么我们可以new一个CountDownLatch(10)的闭锁,每个加载资源的线程执行完后都调用countDown()函数,而线程A则在需要的资源准备齐全之前因调用await函数而被阻塞,当计数器的值为0时,线程A就会被唤醒继续执行。

    知行合一

      案例请戳《Java 使用线程池和CountDownLatch分批插入或者更新数据》。

    结束语

      JUC CountDownLatch是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。原理:它通过一个计数器来实现的,计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就减一。当计数器递减至零时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就被唤醒,恢复执行任务。

      老铁们, 因个人能力有限,难免有瑕疵,如果发现bug或者有更好的建议,那么请在文章下方留言!

  • 相关阅读:
    java面试题总汇
    数据库sql语句规则
    docker安装redis(网上很多答案都是错误的,小心误入歧途!)
    docker 安装redis后,可视化工具无法连接
    Session
    #{}和${}区别
    axios和ajax区别
    Git使用
    Git常用命令
    如何简单粗暴的搞定dubbo调用模块
  • 原文地址:https://www.cnblogs.com/east7/p/16211313.html
Copyright © 2020-2023  润新知