一、继承关系
public class CountDownLatch
功能:让n个线程(线程之间是共享的关系)等待另外m个线程执行完任务后再开始执行。
具体流程:将n个调用countDownLatch.await()的线程添加到CLH队列中,m个线程中最后一个执行countDownLatch.countDown()方法的线程执行tryReleaseShared成功,唤醒CLH队列中的n个共享线程。
说明:不要求和锁一起使用。初始化时指定m个线程的数量。
二、成员变量
private final Sync sync;//继承自AQS
//指定需要等待的线程的个数
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
三、内部类
(1)Sync
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
//构造方法,设置state的个数,表示能获取的锁的个数
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
//共享锁实现,尝试获取共享锁
protected int tryAcquireShared(int acquires) {
//state==0则获取成功,否则失败
return (getState() == 0) ? 1 : -1;
}
//释放共享锁。
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0)
return false;
//释放一个共享锁,state减1
int nextc = c-1;
//CAS更新state的值
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
四、方法说明
(1)countDown:执行一次,state减1一次,最后执行countDown的线程负责唤醒CLH中等待获取锁的所有共享状态的node中的线程
public void countDown() {
//调用AQS的releaseShared方法,释放成功则进行doReleaseShared()方法,负责唤醒后继线程。
sync.releaseShared(1);
}
//中断则抛出异常
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//中断抛出异常,超时则节点状态转换为cancelled
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
五、使用实例
说明:两个共享线程等待另外5个线程执行任务,当5个线程都执行完成后,这两个共享线程再开始运行
public static void testCountDown(){
CountDownLatch countDownLatch=new CountDownLatch(5);
Thread[] threads=new Thread[5];
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
LockSupport.parkNanos(1000);
System.out.println("张三开始等待");
try {
countDownLatch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("人到齐了,可以开会!");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
LockSupport.parkNanos(1000);
System.out.println("李四开始等待");
try {
countDownLatch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("人到齐了,可以开会!");
}
}).start();
for(int i=1;i<=5;i++){
threads[i-1]=new myThread("persion"+i, countDownLatch);
threads[i-1].start();
}
}
class myThread extends Thread{
String name;
CountDownLatch countDownLatch;
public myThread(String name,CountDownLatch countDownLatch){
super();
this.name=name;
this.countDownLatch=countDownLatch;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+"来了!");
countDownLatch.countDown();
}
}
输出:
张三开始等待
李四开始等待
persion4来了!
persion3来了!
persion2来了!
persion1来了!
persion5来了!
人到齐了,可以开会!
人到齐了,可以开会!