用法
允许一个或多个线程等待直到
在其他线程中执行的一组操作完成才开始运行。
原理
CountDownLatch在初始化时,需要指定用给定一个整数作为计数器。当调用countDown方法时,计数器会被减1;当调用await方法时,如果计数器大于0时,线程会被阻塞,一直到计数器被countDown方法减到0时,线程才会继续执行。计数器是无法重置的,当计数器被减到0时,调用await方法都会直接返回。
- 主线程调用countDown();
- 任务线程调用await();
源码解读
成员变量
- private final Sync sync; //sync内部类
方法
- public CountDownLatch(int count); //构造方法
- public void await() throws InterruptedException //
- public boolean await(long timeout, TimeUnit unit)
- public void countDown()
- public long getCount()
public class CountDownLatch {
/**
* 内部类Sync 继承AQS 同步控制
* 使用AQS状态表示计数。
*/
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
//Sync构造
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
//内部类Sync
private final Sync sync;
/**
* 构造方法 指定等待线程的个数
*/
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
/**
* await() 是主线程需要条用的方法
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* await() 是主线程需要条用的方法 有超时时间
*/
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
/**
* 需要执行的线程调用方法
*/
public void countDown() {
sync.releaseShared(1);
}
public long getCount() {
return sync.getCount();
}
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}
例子
下面我们写一个例子:需求是选手比赛,裁判要等选手就位,然后宣布比赛开始!
/**
* Test
*
* @Desciption
* @create create by pengzc 2020/08/07
**/
public class Test {
/**
* 选手线程
*/
public static class ThreadPlayer implements Runnable{
//CountDownLatch
private CountDownLatch latch;
//选手名字
private String name;
public ThreadPlayer (CountDownLatch latch,String name) {
this.latch = latch;
this.name = name;
}
@Override
public void run() {
System.out.println(name+"就位");
latch.countDown();
}
}
/**
* 裁判线程
*/
public static class ThreadReferee extends Thread{
//CountDownLatch
private CountDownLatch latch;
//名字
private String name;
public ThreadReferee(CountDownLatch latch, String name) {
this.latch = latch;
this.name = name;
}
@Override
public void run() {
try {
System.out.println(name+"准备比赛!");
latch.await();
System.out.println(name+"比赛开始!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//定义一个大小为2的CountDownLatch
CountDownLatch latch = new CountDownLatch(2);
new Thread(new ThreadPlayer(latch,"选手软妹")).start();
new Thread(new ThreadPlayer(latch,"选手棉花糖")).start();
ThreadReferee referee = new ThreadReferee(latch,"裁判");
new Thread(referee).start();
}
}
运行结果
选手软妹就位
选手棉花糖就位
裁判准备比赛!
裁判比赛开始!