什么是countDownlatch
CountDownLatch是一个同步工具类,它通过一个计数器来实现的,初始值为线程的数量。每当一个线程完成了自己的任务,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已执行完毕,然后在等待的线程就可以恢复执行任务。
方法详解
CountDownLatch(int count):count为计数器的初始值(一般需要多少个线程执行,count就设为几)。
countDown(): 每调用一次计数器值-1,直到count被减为0,代表所有线程全部执行完毕。
getCount():获取当前计数器的值。
await(): 等待计数器变为0,即等待所有异步线程执行完毕。
boolean await(long timeout, TimeUnit unit): 此方法与await()区别:
- 此方法至多会等待指定的时间,超时后会自动唤醒,若 timeout 小于等于零,则不会等待
- boolean 类型返回值:若计数器变为零了,则返回 true;若指定的等待时间过去了,则返回 false
CountDownLatch应用场景
- 某个线程需要在其他n个线程执行完毕后再向下执行
- 多个线程并行执行同一个任务,提高响应速度
实际案例
实现在无多条件查询的接口下完成多条件查询,即批处理调用接口查询,为了保证获取的性能问题,此处需要使用此技术。
前提是该接口支持该数量级的qps。
List<String> ids = new ArrayList<>(Arrays.asList("陈", "王", "李"));
List<String> nameList = Collections.synchronizedList(new ArrayList<>());
CountDownLatch countDownLatch = new CountDownLatch(ids.size());
for (String s : ids) {
ThreadPoolUtil.execute(() -> {
// 此处方法为调用外部接口,根据姓氏条件模糊查询用户列表,获取包含此姓氏的所有名字列表(假设没有多条件查询下)
List<String> exhibitionDetailsSplit = SignUtil.advancedQueryMultipleConditions(s);
nameList.addAll(exhibitionDetailsSplit);
countDownLatch.countDown();
});
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
log.error("exception: {}", e.getMessage());
}
ThreadPoolUtil工具类
@Slf4j
public class ThreadPoolUtil {
private static ExecutorService executor = Executors.newCachedThreadPool();
public static void execute(Runnable task) {
try {
executor.execute(task);
} catch (Exception e) {
log.error("线程池异常:{}", e.getMessage());
}
}
public static void shutdown() {
executor.shutdown();
}
}