CountDownLatch和CyclicBarrier都有一个计数器
CountDownLatch countDownLatch = new CountDownLatch(4); CyclicBarrier cyclicBarrier = new CyclicBarrier(4)
CountDownLatch 是在 countDownLatch.countDown()执行后 4-1 等到4减到0后,就可以继续执行程序,否则会一直等待
CyclicBarrier是在cyclicBarrier.await()执行后 也是4-1 等到4减到0后,也可以继续执行程序,否则一直会等待。
两者有什么区别呢?举个例子
办公室有4个人
CountDownLatch是 你们4个人干完活了,等你们都干完活了,我来讲两句
CyclicBarrier是你们4个干完活了,等都干完活了,你们接着继续干
闭锁CountDownLatch用于等待事件,而栅栏CyclicBarrier用于等待其他线程。
CountDownLatch是4个线程都执行完countDown后,程序继续向下运行,后面的事和4个线程无关,和CountDownLatch.await()此方法等待你们4个干完活有关。这里类似 你自己diy电脑,买了主机,cpu,电源 ,主板,等等,必须等所有快递到了之后你才能安装电脑。
CyclicBarrier是4个线程执行到某一步后都开始await,等等待的人到齐后继续干活。这里类似王者荣耀,10个人进入加载页面后,必须等10个人全部加载完成后才能进入游戏界面
来demo
@Test
public void testCount() throws InterruptedException {
ArrayList<String> list = Lists.newArrayList("cpu", "显示器", "主板", "电源", "机箱", "鼠标", "键盘");
int size = list.size();
ExecutorService executorService = Executors.newFixedThreadPool(size);
//程序计数器
CountDownLatch countDownLatch = new CountDownLatch(size);
for (int i = 0; i < size; i++) {
int finalI = i;
executorService.submit(() -> {
System.out.println("快递【"+list.get(finalI)+"】已送达");
countDownLatch.countDown();
long count = countDownLatch.getCount();
System.out.println("快递总共有"+size+"个,目前还剩下"+count+"个未到达");
});
Thread.sleep(10);
}
Thread.sleep(1000);
countDownLatch.await();
System.out.println("快递已经到达完毕,开始组装玩游戏");
//线程池 等待10s
executorService.awaitTermination(10, TimeUnit.SECONDS);
//关闭线程 其实是将线程状态设置为中断标志 必须等待所有线程处理完任务,才能完全关闭
executorService.shutdown();
}
@Test
public void testCyclicBarrier() throws InterruptedException {
ArrayList<String> list = Lists.newArrayList("user1", "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9", "user10");
int size = list.size();
ExecutorService executorService = Executors.newFixedThreadPool(size);
CyclicBarrier cyclicBarrier = new CyclicBarrier(size, () -> {
System.out.println("所有人加载完毕,欢迎进入游戏!");
});
for (int i = 0; i < list.size(); i++) {
int finalI = i;
executorService.submit(
new Thread(() -> {
try {
System.out.println("用户【" + list.get(finalI) + "】选完英雄,进入加载界面,等待其他人加载.....");
cyclicBarrier.await(); // 等待其他线程到齐,到齐了之后就会执行一次
System.out.println("用户【" + list.get(finalI) + "】加载游戏完成,进入游戏,开始游戏");
} catch( Exception e) {
e.printStackTrace();
}
}));
}
executorService.awaitTermination(10, TimeUnit.SECONDS);
executorService.shutdown();
}