CountDownLatch模拟田径赛跑
群里得一面试题,正好用来练手
现有一场田径比赛,共有8个选手参赛。他们编号分别为: A,B,C,D,E,F,G,H; 赛事观察员分别在开始后 20s和30s拍下两张照片,各个选手的排名情况如下, 20s:F,A,H,G,C,B,E,D;30s:G,H,A,C,F,D,B,E;请你写出一个程序, 模拟出这些参赛选手在20-30s这10s的内排名变化,每1s显示一次排名。
主要是考察countDownLatch。
计算的时候clone出快照。避免计算的过程中瞬间值又有变化,导致算出的值不准确。
拍照也就是存一下快照而已。
ps:可能是对题理解有误,下面的效果不追求固定名次。
固定名次的写法思路是:写死 各个选手在20s的时候的距离(a),根据a减去各个选手当前的距离(0),然后再 随机到每一秒,就是选手每秒的跑的距离。 30s 的时候重新定义一下目标距离(b),b减去选手的20s时候的距离a,随机到每一秒。
效果
代码
package com.gkwind.concurrent;import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;/*** 现有一场田径比赛,共有8个选手参赛。他们编号分别为: A,B,C,D,E,F,G,H;* 赛事观察员分别在开始后 20s和30s拍下两张照片,各个选手的排名情况如下,* 20s:F,A,H,G,C,B,E,D;30s:G,H,A,C,F,D,B,E;请你写出一个程序,* 模拟出这些参赛选手在20-30s这10s的内排名变化,每1s显示一次排名。** @Author thewindkee* @Date 2019/7/18 0018 22:36*/
public class Athletics {static final CountDownLatch START_GUN = new CountDownLatch(1);static final LocalDateTime DATE_TIME = LocalDateTime.now();static volatile boolean over = false;static long startTime;static final int PICTURE_TIME = 20;static final int PICTURE_TIME2 = 30;public static void main(String[] args) throws InterruptedException {int num = 8;CountDownLatch latch = new CountDownLatch(num);List<Athlete> athletes = initAthletes(num, latch);athletes.stream().forEach(athlete -> athlete.start());System.out.println("裁判等待选手就位");Computer computer = new Computer(athletes);computer.start();latch.await();System.out.println(DATE_TIME + "时裁判开枪");startTime = Instant.now().toEpochMilli();START_GUN.countDown();computer.join();computer.showPhotos();}private static List<Athlete> initAthletes(int num, CountDownLatch latch) {return IntStream.range(0, num).mapToObj(i -> new Athlete(String.valueOf((char) ('A' + i)), latch)).collect(Collectors.toList());}static class Computer extends Thread {List<Picture<Athlete>> pictures = new ArrayList<>();static class Picture<E> {final List<E> pictureItems;final long timestamp;public Picture(List<E> items) {this.pictureItems = Collections.unmodifiableList(items);;this.timestamp = Instant.now().toEpochMilli();}public void show() {pictureItems.stream().forEach(item -> System.out.println(item));}@Overridepublic String toString() {return "照片拍摄于" + LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()) +":" + pictureItems +'}';}}final List<Athlete> athletes;public Computer(List<Athlete> athletes) {this.athletes = Collections.unmodifiableList(athletes);}public List<Athlete> compute() {return athletes.stream().map(new Function<Athlete, Athlete>() {@Overridepublic Athlete apply(Athlete athlete) {try {//拍照,返回运动员的成绩快照return (Athlete) athlete.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}throw new RuntimeException("计算机故障");}}).sorted(Comparator.reverseOrder()).collect(Collectors.toList());}@Overridepublic void run() {try {System.out.println("电脑已启动");START_GUN.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("\n电脑开始工作");sleepThenTakeFirstPhoto();while (!over && !isInterrupted()) {System.out.println();long currentSecond = (Instant.now().toEpochMilli() - startTime) / 1000 + 1;try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}List<Athlete> sortedAthletes = compute();System.out.print(currentSecond + "秒: ");sortedAthletes.stream().forEach(athlete -> System.out.print(athlete.getName() + " " + athlete.curLength + " "));if (currentSecond >= PICTURE_TIME2) {//第二次拍照takePhoto(sortedAthletes);over = true;break;}}}private void sleepThenTakeFirstPhoto() {while (true) {long currentSecond = (Instant.now().toEpochMilli() - startTime) / 1000 + 1;try {TimeUnit.SECONDS.sleep(1);System.out.print(currentSecond + "秒 ");} catch (InterruptedException e) {e.printStackTrace();}if (PICTURE_TIME <= currentSecond) {System.out.println(currentSecond + "秒");//第一次拍照List<Athlete> sortedAthletes = compute();System.out.print(currentSecond + "秒: ");sortedAthletes.stream().forEach(athlete -> System.out.print(athlete.getName() + " " + athlete.curLength + " "));takePhoto(sortedAthletes);break;}}}private <E> void takePhoto(List<E> datas) {System.out.print("\ttakePhoto");pictures.add(new Picture(datas));}public void showPhotos() {System.out.println("\n打印照片");pictures.stream().forEach(e -> System.out.println(e));}}static class Athlete extends Thread implements Comparable<Athlete>, Cloneable {final CountDownLatch latch;final String name;private volatile int curLength = 0;public Athlete(String name, CountDownLatch latch) {super(name);this.name = name;this.latch = latch;}public void ready() {System.out.println(this.name + " 进场");try {TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(100));} catch (InterruptedException e) {e.printStackTrace();}System.out.println("选手" + this.name + " 准备好了,等待发令枪");latch.countDown();}@Overridepublic void run() {ready();try {START_GUN.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.print("选手" + this.name + " 起跑\t");doRun();}private void doRun() {while (!over && !isInterrupted()) {curLength += ThreadLocalRandom.current().nextInt(8)+1;//模拟秒速try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}@Overridepublic int compareTo(Athlete o) {return Integer.compare(this.curLength, o.curLength);}@Overrideprotected Object clone() throws CloneNotSupportedException {Athlete athlete = new Athlete(this.name, null);athlete.curLength = this.curLength;return athlete;}@Overridepublic String toString() {return "Athlete{" +"name='" + name + '\'' +", curLength=" + curLength +'}';}}
}
CountDownLatch模拟田径赛跑相关推荐
- 用CountDownLatch模拟跑步比赛
示例代码 public class Test {//比赛开始的倒计时private static CountDownLatch countDownLatchStart = new CountDownL ...
- 使用CyclicBarrier模拟百米赛跑
使用CyclicBarrier模拟百米赛跑 什么是CyclicBarrier 怎么使用CyclicBarrier 使用CyclicBarrier模拟百米赛跑 大概流程: 原代码 输出结果 什么是Cyc ...
- 使用CountDownLatch模拟高并发场景
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java ...
- phaser模拟百米赛跑
package com.brendan.cn.concurrent.match;import java.util.concurrent.Phaser;public class Match {// 模拟 ...
- java count 在哪一类里_java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用...
先来讲解一下Semaphore信号灯的作用: 可以维护当前访问自身的线程个数,并提供了同步机制, 使用semaphore可以控制同时访问资源的线程个数 例如,实现一个文件允许的并发访问数. 请看下面的 ...
- java不完全教程附编码示例
Java不完全教程第一章Java预备知识常用DOS命令help,dir,md,cd,rd,del,copy,move,start,type,cls,attrib配置环境变量JAVA_HOME C:\s ...
- java小车赛跑_Java模拟赛跑过程
Java并发面试中的一个经典问题--手写代码模拟赛跑过程.该问题考查CountDownLatch的用法,比Java实现生产者-消费者模型的考查更直接: 对Java并发模型的理解 对Java并发编程接口 ...
- Java CountDownLatch的两种常用场景
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/120506758 本文出自[赵彦军的博客] 文章目录 简介 场景1 让多个线程等待: ...
- Java 模拟多线程并发案例
一.使用 CountDownLatch 模拟多线程并发(并行) CountDownLatch 介绍: countDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBar ...
最新文章
- java list《》_Java中List集合的遍历
- 鸿蒙兼容安卓app 为什么还要生态,就因为鸿蒙兼容安卓APP,中兴就宣布弃用?...
- 今日arXiv精选 | 9篇ICCV 2021最新论文
- 用shell批量转储表
- eclipse代码编辑区字符串自动转义设置
- (七)、Java异常类型及处理
- 关于字体的一些知识,以及分享一些免费可商用字体
- 云服务器Tomcat版本升级(Tomcat6升级至Tomcat7和Tomcat8)问题总结
- 国际贸易基础(三)商检
- 代码粘贴至word后,黑色背景处理
- 翼灵物联工作室第一次考试总结
- 学习CSS的background属性及其取值(实践)
- 如何用几何绘图软件给半圆填色?
- linux gzip 4G,Linux gzip命令
- 关于C++中Eigen库效率提升的思考
- eclipse开发android入门学习
- php如何继续提升技术?一个php技术栈后端猿的知识储备仓库
- DELPHI HOOK随手笔记
- 无领导小组讨论面试真题解析(三)
- Jenkins 流水线说明