一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情。
接着上一篇文章 【并发编程】- CountDownLatch 多线程集合同步点
虽然按预期运行成功,但并不能保证在main主线程中执行了service.startMatch()时,所有的工作线程都是wait状态,因为某些线程有可能准备的时间花费较长,可能耗用的时间超过2秒,这时如果在第2秒时调用service.startMatch()方法达不到“唤醒所有线程”继续向下运行的目的了,就是裁判员没有等全部的运动员到来时,就让发令枪响起开始比赛了,这是不符合逻辑,所以需要进行优化。
创建运动员线程代码如下:
public class Runner implements Runnable {
private CountDownLatch comingTag; //裁判等待所有运动员到来
private CountDownLatch waitTag; //等待裁判说准备开始
private CountDownLatch waitRunTag; //等待起跑
private CountDownLatch beginTag;//起跑
private CountDownLatch endTag;//所有运动员到达终点
public Runner(CountDownLatch comingTag,CountDownLatch waitTag,CountDownLatch waitRunTag,CountDownLatch beginTag,CountDownLatch endTag) {
super();
this.comingTag=comingTag;
this.waitTag=waitTag;
this.waitRunTag=waitRunTag;
this.beginTag=beginTag;
this.endTag=endTag;
}
@Override
public void run() {
try {
System.out.println("运动员使用不同方式到达起跑点,正向这边走!");
Thread.sleep((int)(Math.random()*1000));
System.out.println("运动员"+Thread.currentThread().getName()+" 到起跑点了! ");
comingTag.countDown();
System.out.println("等待裁判说准备!");
waitTag.await();
System.out.println("各就各位!准备起跑姿势! ");
Thread.sleep((int)(Math.random()*1000));
waitRunTag.countDown();
beginTag.await();
System.out.println("运动员"+Thread.currentThread().getName()+"起跑 并且跑过程用时不确定");
Thread.sleep((int)(Math.random()*1000));
endTag.countDown();
System.out.println("运动员"+Thread.currentThread().getName()+"到达终点!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行类代码如下:
public class RunnerMatch {
public static void main(String[] args) throws InterruptedException {
CountDownLatch comingTag = new CountDownLatch(5);
CountDownLatch waitTag = new CountDownLatch(1);
CountDownLatch waitRunTag = new CountDownLatch(5);
CountDownLatch beginTag = new CountDownLatch(1);
CountDownLatch endTag = new CountDownLatch(5);
Runner[] runners = new Runner[5];
for (int i = 0; i <runners.length ; i++) {
runners[i] = new Runner(comingTag, waitTag, waitRunTag, beginTag, endTag);
new Thread(runners[i]).start();
}
System.out.println("裁判员在等待选手的到来!");
comingTag.await();
System.out.println("裁判员看到所有运动员来了,各就各位前巡视用时5秒");
Thread.sleep(5000);
waitTag.countDown();
System.out.println("各就各位!");
waitRunTag.await();
Thread.sleep(2000);
System.out.println("发令枪响起!");
beginTag.countDown();
endTag.await();
System.out.println("所有运动员到达,统计比赛名次!");
}
}
运行结果如下:
裁判员在等待选手的到来!
运动员使用不同方式到达起跑点,正向这边走!
运动员使用不同方式到达起跑点,正向这边走!
运动员使用不同方式到达起跑点,正向这边走!
运动员使用不同方式到达起跑点,正向这边走!
运动员使用不同方式到达起跑点,正向这边走!
运动员Thread-4 到起跑点了!
等待裁判说准备!
运动员Thread-0 到起跑点了!
等待裁判说准备!
运动员Thread-1 到起跑点了!
等待裁判说准备!
运动员Thread-2 到起跑点了!
等待裁判说准备!
运动员Thread-3 到起跑点了!
等待裁判说准备!
裁判员看到所有运动员来了,各就各位前巡视用时5秒
各就各位!准备起跑姿势!
各就各位!准备起跑姿势!
各就各位!准备起跑姿势!
各就各位!
各就各位!准备起跑姿势!
各就各位!准备起跑姿势!
发令枪响起!
运动员Thread-4起跑 并且跑过程用时不确定
运动员Thread-2起跑 并且跑过程用时不确定
运动员Thread-1起跑 并且跑过程用时不确定
运动员Thread-3起跑 并且跑过程用时不确定
运动员Thread-0起跑 并且跑过程用时不确定
运动员Thread-2到达终点!
运动员Thread-0到达终点!
运动员Thread-1到达终点!
运动员Thread-4到达终点!
运动员Thread-3到达终点!
所有运动员到达,统计比赛名次!