CountDownLatch
是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier
、Semaphore
、ConcurrentHashMap
和BlockingQueue
,它们都存在于java.util.concurrent包下。CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。
CountDownLatch是通过一个计数器
来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
关于countDownLatch.await(10, TimeUnit.MILLISECONDS) 可选时间参数
, 就多额了一个阻塞解除条件, 计数到0和时间到0, 其中一个条件满足就可以解除阻塞等待线程.
package com.bestksl.example.aqs;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
@Slf4j
public class CountDownLatchExample2 {
static final int clientTotal = 500; //并发总计数
static final int threadTotal = 20; //并发线程最大值
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
Semaphore semaphore = new Semaphore(threadTotal);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i {
try {
semaphore.acquire();
p(n);
semaphore.release();
} catch (InterruptedException e) {
log.info(e.getMessage());
} finally {
countDownLatch.countDown(); // 因为只是示范, 所以放到了finally中保证计数, 如有特殊情况应该加入处理逻辑
}
});
}
executorService.execute(() -> {
try {
countDownLatch.await(10, TimeUnit.MILLISECONDS);// 加上时间参数可以强行到时激活await()
System.out.println("done");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executorService.shutdown();
}
//并发方法
private static void p(int n) throws InterruptedException {
Thread.sleep(200);
log.info(n + "");
Thread.sleep(200);
}
}