“J.U.C”:CountDownlatch (r)
来源:互联网 发布:淘宝买iphone8靠谱吗 编辑:程序博客网 时间:2024/05/21 15:50
上篇博文(【Java并发编程实战】—–“J.U.C”:CyclicBarrier)LZ介绍了CyclicBarrier。CyclicBarrier所描述的是“允许一组线程互相等待,直到到达某个公共屏障点,才会进行后续任务”。而CountDownlatch和它也有一点点相似之处:CountDownlatch所描述的是“在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待”。在JDK API中是这样阐述的:
用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。(await()方法是相当于获取锁,条件不满足阻塞,等待释放锁后进行通知,countDown()方法相当于释放锁,然后进行通知等待线程的操作)
CountDownLatch 是一个通用同步工具,它有很多用途。将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。
CountDownLatch 的一个有用特性是,它不要求调用 countDown 方法的线程等到计数到达零时才继续,而在所有线程都能通过之前,它只是阻止任何线程继续通过一个 await。
虽然,CountDownlatch与CyclicBarrier有那么点相似,但是他们还是存在一些区别的:
1、CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。
2、 CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。
CountDownLatch分析
CountDownLatch结构如下:
从上图中可以看出CountDownLatch依赖Sync,其实CountDownLatch内部采用的是共享锁来实现的(内部Sync的实现可以看出)。它的构造函数如下:
CountDownLatch(int count):构造一个用给定计数初始化的 CountDownLatch。
以下源代码可以证明,CountDownLatch内部是采用共享锁来实现的:
CountDownLatch提供了await方法来实现:
await():使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
await(long timeout, TimeUnit unit): 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
await内部调用sync的acquireSharedInterruptibly方法:
acquireSharedInterruptibly()的作用是获取共享锁。如果在获取共享锁过程中线程中断则抛出InterruptedException异常。否则通过tryAcquireShared方法来尝试获取共享锁。如果成功直接返回,否则调用doAcquireSharedInterruptibly方法。
tryAcquireShared源码:
tryAcquireShared方法被CountDownLatch重写,他的主要作用是尝试着获取锁。getState == 0 表示锁处于可获取状态返回1否则返回-1;当tryAcquireShared返回-1获取锁失败,调用doAcquireSharedInterruptibly获取锁:
该方法当中的方法,前面博客都讲述过,请参考:【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析、【Java并发编程实战】—–“J.U.C”:Semaphore。
CountDownLatch,除了提供await方法外,还提供了countDown(),countDown所描述的是“递减锁存器的计数,如果计数到达零,则释放所有等待的线程。”,源码如下:
countDown内部调用releaseShared方法来释放线程:
tryReleaseShared,同时被CountDownLatch重写了:
总结:
CountDownLatch内部通过“共享锁”实现。在创建CountDownLatch时,需要传递一个int类型的count参数,该count参数为“锁状态”的初始值,该值表示着该“共享锁”可以同时被多少线程获取。当某个线程调用await方法时,首先判断锁的状态是否处于可获取状态(其条件就是count==0?),如果共享锁可获取则获取共享锁,否则一直处于等待直到获取为止。当线程调用countDown方法时,计数器count – 1。当在创建CountDownLatch时初始化的count参数,必须要有count线程调用countDown方法才会使计数器count等于0,锁才会释放,前面等待的线程才会继续运行。
实例
员工开会只有当所有人到期之后才会开户。我们初始化与会人员为3个,那么CountDownLatch的count应为3:
参加与会人员Participater:
Test:
运行结果:
- “J.U.C”:CountDownlatch (r)
- J.U.C之CountDownLatch
- “J.U.C”:Condition (r)
- “J.U.C”:Semaphore (r)
- “J.U.C”:CyclicBarrier (r)
- “J.U.C”:Phaser (r)
- “J.U.C”:ReentrantLock之一简介 (r)
- “J.U.C”:锁,lock (r)
- “J.U.C”:CAS操作 (r)
- “J.U.C”:CLH队列锁 (r)
- 浅析J.U.C的AQS(一):CountDownLatch
- 浅析J.U.C的AQS(一):CountDownLatch
- 【Java并发编程实战】—–“J.U.C”:CountDownlatch
- 【Java并发编程实战】—–“J.U.C”:CountDownlatch
- 【Java并发编程实战】-----“J.U.C”:CountDownlatch
- “J.U.C”:ReentrantLock之二lock方法分析 (r)
- “J.U.C”:ReentrantLock之三unlock方法分析(r)
- “J.U.C”:AQS分析(一)(r)
- 大地测量海洋测量数据表格
- Shader第十三讲 Alpha混合
- 自定义控件--滑动删除
- TCP通信的三次握手和四次撒手的详细流程(顿悟)
- dts中会用到的MODULE_DEVICE_TABLE
- “J.U.C”:CountDownlatch (r)
- android:自定义温度计View
- greenplum安装
- CDISC SDTM MI domain学习笔记
- php 使用ajax文本框模糊查询
- “J.U.C”:Phaser (r)
- ASP.NET 5 Dependency Injection with Autofac
- iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
- angular-按需加载angularjs和$http.post的二三事