CountDownLatch模擬陸上競技

8815 ワード

グループの中で面接の問題があって,ちょうど手を練習するのに使われている.
現在陸上競技が1試合あり、8選手が出場している.彼らの番号はそれぞれ:A,B,C,D,E,F,G,H;試合オブザーバーはそれぞれ開始後20 sと30 sに2枚の写真を撮り、各選手の順位は以下の通り、20 s:F、A、H、G、C、B、E、D;30s:G,H,A,C,F,D,B,E;これらの参加選手が20-30 sの10 s以内の順位の変化をシミュレートし、1 sごとに順位を表示するプログラムを書いてください.
主にcountDownLatchを考察する.計算時にcloneがスナップショットを出します.計算中に瞬間値が変化することを避け、算出された値が不正確になる.
写真を撮るのはスナップショットを保存するだけです.ps:問題の理解が間違っているかもしれませんが、次の効果は固定順位を追求しません.固定順位の書き方は、各選手が20 sのときの距離(a)を書き殺し、aから各選手の現在の距離(0)を減算し、ランダムに毎秒、つまり選手が毎秒走る距離とする.30 sのときに目標距離(b)を再定義し、bから選手の20 sを引いたときの距離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 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 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> pictures = new ArrayList<>();

        static class Picture {
            final List pictureItems;
            final long timestamp;

            public Picture(List items) {
                this.pictureItems = Collections.unmodifiableList(items);
                ;
                this.timestamp = Instant.now().toEpochMilli();
            }

            public void show() {
                pictureItems.stream().forEach(item -> System.out.println(item));
            }

            @Override
            public String toString() {
                return "     " + LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()) +
                    ":" + pictureItems +
                    '}';
            }
        }

        final List athletes;

        public Computer(List athletes) {
            this.athletes = Collections.unmodifiableList(athletes);
        }

        public List compute() {
            return athletes.stream().map(new Function() {
                @Override
                public Athlete apply(Athlete athlete) {
                    try {
                        //  ,          
                        return (Athlete) athlete.clone();
                    } catch (CloneNotSupportedException e) {
                        e.printStackTrace();
                    }
                    throw new RuntimeException("     ");
                }
            }).sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        }

        @Override
        public void run() {
            try {
                System.out.println("     ");
                START_GUN.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("
"); 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 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 sortedAthletes = compute(); System.out.print(currentSecond + " : "); sortedAthletes.stream().forEach(athlete -> System.out.print(athlete.getName() + " " + athlete.curLength + " ")); takePhoto(sortedAthletes); break; } } } private void takePhoto(List datas) { System.out.print("\ttakePhoto"); pictures.add(new Picture(datas)); } public void showPhotos() { System.out.println("
"); pictures.stream().forEach(e -> System.out.println(e)); } } static class Athlete extends Thread implements Comparable, 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(); } @Override public 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(); } } } @Override public int compareTo(Athlete o) { return Integer.compare(this.curLength, o.curLength); } @Override protected Object clone() throws CloneNotSupportedException { Athlete athlete = new Athlete(this.name, null); athlete.curLength = this.curLength; return athlete; } @Override public String toString() { return "Athlete{" + "name='" + name + '\'' + ", curLength=" + curLength + '}'; } } }