Java学习-CountDownLatch/CylicBarrier

63 阅读2分钟
  • CountDownLatch

    • CountDownLatch (闭锁) 是一个同步协助类,允许一个或多个线程等待,直到其他线程完成操作集。
    • CountDownLatch使用给定的计数值 (count) 初始化。
    • await方法会阻塞直到当前的计数值被countDown方法的调用达到0,count为0只有所有等待的线程都会被释放,并且随后对await方法的调用会立即返回。
    • 这是一个一次性现象 -- count不会被重置。如果你需要一个重置count的版本,那么请考虑使用CyclicBarrier
    • 作用:

      • 让多个线程等待,模拟并发,让并发线程一起执行
      • 让单个线程等待:多个线程执行完任务后,进行合并汇总
  • CountDownLatch实现原理

    • 底层基于AbstractQueuedSynchronizer(AQS)实现,CouontDownLatch构造函数中指定count直接赋值给AQS的state
    • 每次countDown()调用时计数器值减一,最后减到0时unpark阻塞线程,这一步是由最后一个执行countdowsn方法的线程执行的
    • 而调用await()方式时,当前线程就会判断state属性是否为0,如果为0,则继续往下执行,如果不为0,则使当前线程进入等待状态,知道某个线程将state属性设置为0,其就会唤醒在await() 方法中等待的线程。
  • CountDownLatch与Thread.join的区别

    • CountDownLatch的作用就是允许一个或多个线程等待其他线程完成操作,看起来有点类似join()
    • CountDownLatch可以手动控制在N个线程里调用N次countDown()方法使计数器进行减一操作,也可以在一个线程里面调用n次减一操作
    • 而join() 的实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远等待,所以两者之间相对来说还是CountDownLatch使用起来较为灵活
  • CyclicBarrier

    • CyclicBarrier可以是一定数量的线程反复的在栅栏位置等待。当线程到达栅栏位置时将调用await方法,这个方法将阻塞知道所有线程都到达栅栏位置。如果所有线程都到达栅栏位置,那么栅栏打开,此时所有的线程都将释放,而栅栏将被重置以便下次使用
    • CyclicBarrier字面意思是可重复栅栏,CyclicBarrier和CountDownLatch很像,只是CyclicBarrier可以重复使用
  • CyclicBarrier和CountDownLatch的区别

    • CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置,可以使用多次,所以CyclicBarrier能够处理更复杂的场景
    • CyclicBarrier还提供了一些其他有用的方法,比如getNumberWaiting()方法可以获得CyclicBarrier阻塞的线程数量,isBroken()方法用来了解阻塞的线程是否被中断
    • CountDownLatch允许一个或多个线程等待一组事件的产生,而CyclicBarrier用于等待其他线程到栅栏位置