Java并发30:CountDownLatch(上)–基本方法学习
[超级链接:Java并发学习系列-绪论]
本章主要对CountDownLatch的两种应用场景进行学习。
有关CountDownLatch的基本方法详见上一章:《 Java并发30》
本人所知的CountDownLatch的用法主要有以下两个方面:
下面分别对这两种应用场景进行实例练习。
场景说明:
重点分析:
实例代码:
运动员:
/**
* 运动员
*
* @author hanchao 2018/3/28 20:48
**/
static class Player implements Runnable {
private static final Logger LOGGER = Logger.getLogger(Player.class);
/**
* 哨子
*/
CountDownLatch latch;
public Player(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
//等待吹哨
LOGGER.info("Player[" + name + "] is waiting for the whistle.");
try {
//注意是await(),不是wait()。
//前置是CountDownLatch的方法,后者是Object的方法。
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("Player[" + name + "] is running...");
//跑到终点的时间
Integer time = RandomUtils.nextInt(5000, 9000);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("Player[" + name + "] is has arrived the finish line!");
}
}
裁判:
/**
* 裁判员
*
* @author hanchao 2018/3/28 20:48
**/
static class Referee implements Runnable {
private static final Logger LOGGER = Logger.getLogger(Referee.class);
/**
* 哨子
*/
CountDownLatch latch;
public Referee(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
//准备吹哨
LOGGER.info("Referee[" + name + "] is ready to whistle. 3... 2... 1...!");
//裁判吹哨--countDown()使count减1,当count=0时,所有在latch上await()的线程不再等待
latch.countDown();
}
}
比赛代码:
/**
* 倒计时门闩-示例
*
* @author hanchao 2018/3/28 20:52
**/
public static void main(String[] args) throws InterruptedException {
//示例一:跑步比赛---哨子
//创建 哨子
CountDownLatch latch = new CountDownLatch(1);
//创建 10人赛道
int num = 10;
ExecutorService executorService = Executors.newFixedThreadPool(num);
//运动员上赛道
for (int i = 0; i < num; i++) {
executorService.submit(new Player(latch));
}
//裁判准备
Thread.sleep(1000);
//裁判开始吹哨
new Thread(new Referee(latch)).start();
//等所有人都跑完,关闭跑道
Thread.sleep(10000);
executorService.shutdownNow();
}
运行结果:
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-1] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-2] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-3] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-10] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-9] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-8] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-7] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-6] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-5] is waiting for the whistle.
2018-03-31 22:42:11 INFO CountDownLatchDemo1$Player:46 - Player[pool-1-thread-4] is waiting for the whistle.
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Referee:86 - Referee[Thread-0] is ready to whistle. 3... 2... 1...!
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-1] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-6] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-4] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-5] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-7] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-8] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-9] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-10] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-2] is running...
2018-03-31 22:42:12 INFO CountDownLatchDemo1$Player:54 - Player[pool-1-thread-3] is running...
2018-03-31 22:42:17 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-9] is has arrived the finish line!
2018-03-31 22:42:18 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-8] is has arrived the finish line!
2018-03-31 22:42:18 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-6] is has arrived the finish line!
2018-03-31 22:42:18 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-10] is has arrived the finish line!
2018-03-31 22:42:19 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-7] is has arrived the finish line!
2018-03-31 22:42:19 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-2] is has arrived the finish line!
2018-03-31 22:42:19 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-5] is has arrived the finish line!
2018-03-31 22:42:20 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-4] is has arrived the finish line!
2018-03-31 22:42:20 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-1] is has arrived the finish line!
2018-03-31 22:42:21 INFO CountDownLatchDemo1$Player:62 - Player[pool-1-thread-3] is has arrived the finish line!
场景说明:
-->
前进,战神金刚!-->
前进,战神金刚!重点分析:
实例代码:
机器狮子:
/**
* 机器狮子
* @author hanchao 2018/3/31 23:02
**/
static class MachineLion implements Runnable {
private static final Logger LOGGER = Logger.getLogger(MachineLion.class);
//身体部分
private String name;
//变形计数器
CountDownLatch latch;
public MachineLion(String name, CountDownLatch latch) {
this.name = name;
this.latch = latch;
}
@Override
public void run() {
//花费一些时间进行组装
Integer time = RandomUtils.nextInt(0, 2000);
LOGGER.info(Thread.currentThread().getName() + " [" + name + "] 正在进行组装...");
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
LOGGER.info(Thread.currentThread().getName() + " 我来组成[" + name + "]!");
}
}
战神金刚进行变身:
/**
* CountDownLatch用法2-线程计数器-战神金刚
*
* @author hanchao 2018/3/28 21:34
**/
public static void main(String[] args) throws InterruptedException {
//main就是战神金刚
int num = 5;
//定义 变形计数器
CountDownLatch latch = new CountDownLatch(num);
//定义 线程池
ExecutorService executorService = Executors.newFixedThreadPool(num);
//五个机器狮子纷纷开始组装
executorService.submit(new MachineLion("脚部", latch));
executorService.submit(new MachineLion("腿部", latch));
executorService.submit(new MachineLion("躯干", latch));
executorService.submit(new MachineLion("手臂", latch));
executorService.submit(new MachineLion("头部", latch));
//等待五个机器狮子进行组装
LOGGER.info(Thread.currentThread().getName() + " [战神金刚] 正在等待组装...");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.sleep(100);
//战神金刚开始发威
LOGGER.info(Thread.currentThread().getName() + ": 前进,战神金刚!");
executorService.shutdownNow();
}
运行结果:
2018-03-31 22:59:52 INFO CountDownLatchDemo2:75 - main [战神金刚] 正在等待组装...
2018-03-31 22:59:52 INFO CountDownLatchDemo2$MachineLion:45 - pool-1-thread-2 [腿部] 正在进行组装...
2018-03-31 22:59:52 INFO CountDownLatchDemo2$MachineLion:45 - pool-1-thread-4 [手臂] 正在进行组装...
2018-03-31 22:59:52 INFO CountDownLatchDemo2$MachineLion:45 - pool-1-thread-3 [躯干] 正在进行组装...
2018-03-31 22:59:52 INFO CountDownLatchDemo2$MachineLion:45 - pool-1-thread-5 [头部] 正在进行组装...
2018-03-31 22:59:52 INFO CountDownLatchDemo2$MachineLion:45 - pool-1-thread-1 [脚部] 正在进行组装...
2018-03-31 22:59:53 INFO CountDownLatchDemo2$MachineLion:52 - pool-1-thread-5 我来组成[头部]!
2018-03-31 22:59:53 INFO CountDownLatchDemo2$MachineLion:52 - pool-1-thread-4 我来组成[手臂]!
2018-03-31 22:59:53 INFO CountDownLatchDemo2$MachineLion:52 - pool-1-thread-1 我来组成[脚部]!
2018-03-31 22:59:54 INFO CountDownLatchDemo2$MachineLion:52 - pool-1-thread-2 我来组成[腿部]!
2018-03-31 22:59:54 INFO CountDownLatchDemo2$MachineLion:52 - pool-1-thread-3 我来组成[躯干]!
2018-03-31 22:59:54 INFO CountDownLatchDemo2:83 - main: 前进,战神金刚!