1.CountDownLatch工具类的特点
CountDownLatch是一种通过计数器的方式来允许一个或者多个线程等待其他线程完成操作。通过这个特点可以实现对多个线程的执行顺序的控制。
2.初识CountDownLatch
http://blog.csdn.net/ya_1249463314/article/details/52822580
3.CountDownLatch所属包
package java.util.concurrent;
4.CountDownLatch的继承与实现关系
public class CountDownLatch
5.源码解析
public class CountDownLatch {
/**
* 使用AQS队列同步器来实现计数的
*/
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
//指定计数的构造器
Sync(int count) {
setState(count);
}
//采用AQS的volatile读的方式来获取同步状态值
int getCount() {
return getState();
}
//在共享模式下获取对象的状态,如果成功获取返回1,失败则返回负值
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
//在共享模式下释放对象的状态
protected boolean tryReleaseShared(int releases) {
//死循环方式
for (;;) {
//获取当前对象的同步状态
int c = getState();
//如果同步状态为0,那么说明需要释放锁的对象数为0,返回false
if (c == 0)
return false;
//当前同步状态值减1
int nextc = c-1;
//采用cas乐观锁的方式来将预期值和当前更新值进行比较
if (compareAndSetState(c, nextc))
//当前更新值为0,说明不存在需要释放的对象了。
return nextc == 0;
}
}
}
//定义一个自定义队列同步器
private final Sync sync;
/**
* 创建一个指定计数的构造器
* 初始化自定义队列同步器
*/
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
/**
* 让当前的线程对象一直处于等待的状态,直到计数器为0才停止等待。
* 如果中间产生了中断,那么就停止等待。
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* 在没有超出指定的时间timeout、计数没有达到0、当前线程没有被中断,那么将一直等待。
*/
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
/**
* 采用共享模式来释放锁,如果计数减为0了,那么就释放所有等待的线程,
*/
public void countDown() {
sync.releaseShared(1);
}
/**
* 获取当前计数值(采用原子的方式来获取当前的同步状态值)
*/
public long getCount() {
return sync.getCount();
}
/**
* 打印当前计数值
*/
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}
6.阅读总结
(1)CountDownLatch这个工具类采用同步队列器AQS来实现的。
(2)CountDownLatch释放同步对象,采用AQS的套路:死循环+cas乐观锁的方式来实现的。
(3)CountDownLatch需要注意的是,如果当前计数未CountDown()到0,那么调用await()的线程将处于阻塞无法执行的状态,但是其他的线程依然可以执行,从源码可以看出这个工具是采用共享式(共享=乐观)而非独占式(独占=悲观)来实现。
-----------------------------------------------------jdk1.7