一、说明
1.CountDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。
2.存在于java.util.cucurrent并发包下
二、原理
1.countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
2.是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
三、源码
//构造器
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//将count值减1
public void countDown() {
sync.releaseShared(1);
}
//获取count值
public long getCount() {
return sync.getCount();
}
三、测试
public class CountDownLatchTest {
public static void main(String[] args) {
System.out.println("主线程开始执行~~~~~~");
CountDownLatch latch = new CountDownLatch(2);
ExecutorService ex_1 = Executors.newSingleThreadExecutor();
ex_1.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("子线程1开始执行:" + Thread.currentThread().getName());
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
latch.countDown();
}
});
ex_1.shutdown();
ExecutorService ex_2 = Executors.newSingleThreadExecutor();
ex_2.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("子线程2开始执行:" + Thread.currentThread().getName());
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
latch.countDown();
}
});
ex_2.shutdown();
System.out.println("等待两个子线程执行完毕~~~~~~~");
System.out.println("latch start:" + latch.getCount());
try {
latch.await();
System.out.println("latch end:" + latch.getCount());
}catch (Exception e){
e.printStackTrace();
}
System.out.println("主线程等待子线程执行完毕,继续执行主线程");
}
}
执行结果:
主线程开始执行~~~~~~
子线程1开始执行:pool-1-thread-1
子线程2开始执行:pool-2-thread-1
等待两个子线程执行完毕~~~~~~~
latch start:2
latch end:0
主线程等待子线程执行完毕,继续执行主线程
四、模拟并发
public class CountDownLatchTest {
public static void main(String[] args) {
System.out.println("starting main~~~~~~" + Thread.currentThread().getName());
CountDownLatch countDownLatch = new CountDownLatch(100);
ExecutorService pool = Executors.newCachedThreadPool();
for(int i =0; i< 100; i++){
CountRunable runable = new CountRunable(countDownLatch);
pool.execute(runable);
}
System.out.println("ending main~~~~~~"+ Thread.currentThread().getName());
}
}
class CountRunable implements Runnable{
private CountDownLatch downLatch;
public CountRunable(CountDownLatch downLatch){
this.downLatch = downLatch;
}
@Override
public void run() {
try {
synchronized (downLatch){
downLatch.countDown();
System.out.println("thread counts = " + (downLatch.getCount()));
}
downLatch.await();
System.out.println("concurrency counts = " + (100 - downLatch.getCount()));
}catch (Exception e){
e.printStackTrace();
}
}
}
执行结果:
starting main~~~~~~main
thread counts = 99
thread counts = 98
thread counts = 97
thread counts = 96
thread counts = 95
thread counts = 94
thread counts = 93
thread counts = 92
thread counts = 91
thread counts = 90
thread counts = 89
thread counts = 88
thread counts = 87
thread counts = 86
thread counts = 85
thread counts = 84
thread counts = 83
thread counts = 82
thread counts = 81
thread counts = 80
thread counts = 79
thread counts = 78
thread counts = 77
thread counts = 76
thread counts = 75
thread counts = 74
thread counts = 73
thread counts = 72
thread counts = 71
thread counts = 70
thread counts = 69
thread counts = 68
thread counts = 67
thread counts = 66
thread counts = 65
thread counts = 64
thread counts = 63
thread counts = 62
thread counts = 61
thread counts = 60
thread counts = 59
thread counts = 58
thread counts = 57
thread counts = 56
thread counts = 55
thread counts = 54
thread counts = 53
thread counts = 52
thread counts = 51
thread counts = 50
thread counts = 49
thread counts = 48
thread counts = 47
thread counts = 46
thread counts = 45
thread counts = 44
thread counts = 43
thread counts = 42
thread counts = 41
thread counts = 40
thread counts = 39
thread counts = 38
thread counts = 37
thread counts = 36
thread counts = 35
thread counts = 34
thread counts = 33
thread counts = 32
thread counts = 31
thread counts = 30
thread counts = 29
thread counts = 28
thread counts = 27
thread counts = 26
thread counts = 25
thread counts = 24
thread counts = 23
thread counts = 22
thread counts = 21
thread counts = 20
thread counts = 19
thread counts = 18
thread counts = 17
thread counts = 16
thread counts = 15
thread counts = 14
thread counts = 13
thread counts = 12
thread counts = 11
thread counts = 10
thread counts = 9
thread counts = 8
thread counts = 7
thread counts = 6
thread counts = 5
thread counts = 4
thread counts = 3
thread counts = 2
thread counts = 1
ending main~~~~~~main
thread counts = 0
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
concurrency counts = 100
五、结束语
countDownLatch是一个计数器,线程完成一个记录一个,计数器递减,只能只用一次