CountDownLatch常用方法
CountDownLatch countDownLatch = new CountDownLatch(100);
countDownLatch.countDown():countDownLatch的值减一,100->99
countDownLatch.await():会使线程休眠,直到countDownLatch的值递减到0,才会重新就绪
countDownLatch.await(long, TimeUnit) :休眠,直到countDownLatch的值递减到0或休眠时间结束
CountDownLatch应用场景
典型应用场景一:启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。
package base.threadabout.multhread.countdownlatch;
import java.util.concurrent.*;
/**
* CountDownLatch常用方法:await(),await(long,TimeUnit),countDown()
* await()会使线程休眠,直到countDownLatch的值递减到0,才会重新就绪
* await(long, TimeUnit) 休眠,直到countDownLatch的值递减到0或休眠时间结束
* 大概作用:等所有线程&某些线程都执行完了,再统一执行某个具体功能
*/
public class MainLoadingService {
public static void main(String[] args) throws InterruptedException {
CountDownLatch cdl = new CountDownLatch(5);
ExecutorService pool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
Loading runnable = new Loading(cdl);
pool.execute(runnable);
}
// 线程全部跑完的标志
System.out.println("等待子线程加载组件...");
cdl.await();
System.out.println("所有组件加载完毕,继续执行...");
pool.shutdown();
}
}
class Loading implements Runnable {
private CountDownLatch countDownLatch;
public Loading(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
// 处理业务
String name = Thread.currentThread().getName();
System.out.println("子线程:" + name + "正在加载组件...");
// 业务处理完毕,countDownLatch-1
countDownLatch.countDown();
}
}
结果:
等待子线程加载组件...
子线程:pool-1-thread-1正在加载组件...
子线程:pool-1-thread-2正在加载组件...
子线程:pool-1-thread-3正在加载组件...
子线程:pool-1-thread-4正在加载组件...
子线程:pool-1-thread-5正在加载组件...
所有组件加载完毕,关闭线程池pool...
典型应用场景二:
主线程定义new CountDownLatch(1)。每个子线程先执行await(),进入等待。等待所有子线程都开启,主线程执行countDown(),能确保所有子线程同时开始处理任务。
类似于赛跑,子线程是运动员,await是运动员的预备阶段,主线程是裁判,countDown是裁判的发令枪。枪响运动员才能跑。
package base.threadabout.multhread.countdownlatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RaceGame {
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(5);
CountDownLatch countDownLatch = new CountDownLatch(1);
for (int i = 0; i < 5; i++) {
Player player = new Player(i, countDownLatch);
pool.execute(player);
}
Thread.sleep(1000);
System.out.println("所有选手各就位.....GO!");
countDownLatch.countDown();
pool.shutdown();
}
static class Player implements Runnable{
private int id;
private CountDownLatch countDownLatch;
public Player(int id, CountDownLatch countDownLatch) {
this.id = id;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("参赛选手[" + id +"]号,准备就绪...");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("参赛选手[" + id +"]号,到达终点...");
}
}
}
结果:
参赛选手[0]号,准备就绪...
参赛选手[1]号,准备就绪...
参赛选手[2]号,准备就绪...
参赛选手[3]号,准备就绪...
参赛选手[4]号,准备就绪...
所有选手各就位.....GO!
参赛选手[1]号,到达终点...
参赛选手[3]号,到达终点...
参赛选手[0]号,到达终点...
参赛选手[2]号,到达终点...
参赛选手[4]号,到达终点...