diff --git a/src/main/java/com/example/tortoisehare/TortoiseHareRace.java b/src/main/java/com/example/tortoisehare/TortoiseHareRace.java index ed1866f67fe471aba10efb6094fe7acf8ab8702a..fe5b29a4fd147596af348dcd0d830d5c1f10dce2 100644 --- a/src/main/java/com/example/tortoisehare/TortoiseHareRace.java +++ b/src/main/java/com/example/tortoisehare/TortoiseHareRace.java @@ -1,123 +1,387 @@ package com.example.tortoisehare; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + public class TortoiseHareRace { - private static final int RACE_DISTANCE = 50; - private static volatile int tortoisePosition = 0; - private static volatile int harePosition = 0; - private static volatile boolean raceFinished = false; + private static final int RACE_DISTANCE = 30; + private static final Lock mainLock = new ReentrantLock(); + private static final Condition raceCondition = mainLock.newCondition(); + private static final AtomicBoolean raceFinished = new AtomicBoolean(false); private static volatile String winner = ""; - public static void main(String[] args) { - System.out.println("龟兔赛跑开始!"); - System.out.println("终点距离: " + RACE_DISTANCE + " 步\n"); - - // 创建乌龟线程 - Thread tortoiseThread = new Thread(() -> { - while (tortoisePosition < RACE_DISTANCE && !raceFinished) { - // 乌龟稳步前进 - tortoisePosition++; - - // 检查是否到达终点 - if (tortoisePosition >= RACE_DISTANCE) { - raceFinished = true; - winner = "T"; - break; + // 参赛者接口 + static interface Racer extends Runnable { + String getName(); + int getPosition(); + String getSymbol(); + void stopRacing(); + } + + // 乌龟实现类 + static class Tortoise implements Racer { + private final String name; + private volatile int position; + private final String symbol; + private final Lock printLock; + private volatile boolean stopped = false; + + public Tortoise(String name, Lock printLock) { + this.name = name; + this.position = 0; + this.symbol = "🐢"; + this.printLock = printLock; + } + + @Override + public void run() { + try { + while (!stopped && position < RACE_DISTANCE && !raceFinished.get()) { + // 乌龟稳步前进 + position += 2; + if (position > RACE_DISTANCE) position = RACE_DISTANCE; + + // 检查是否到达终点 + checkFinish(); + + // 打印状态 + printStatus(); + + // 使用条件等待替代sleep,可被立即唤醒 + mainLock.lock(); + try { + // 等待100ms或直到比赛结束 + raceCondition.awaitNanos(100_000_000); // 100ms + } finally { + mainLock.unlock(); + } } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + private void checkFinish() { + if (position >= RACE_DISTANCE && raceFinished.compareAndSet(false, true)) { + winner = name; + // 通知所有线程比赛结束 + mainLock.lock(); try { - Thread.sleep(200); // 乌龟较慢 - printTortoiseStatus(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - break; + raceCondition.signalAll(); + } finally { + mainLock.unlock(); } + printFinishStatus(); } - }, "Tortoise"); - - // 创建兔子线程 - Thread hareThread = new Thread(() -> { - while (harePosition < RACE_DISTANCE && !raceFinished) { - // 兔子跳跃前进 - harePosition += 2; - - // 检查是否到达终点 - if (harePosition >= RACE_DISTANCE) { - raceFinished = true; - winner = "H"; - break; + } + + private void printStatus() { + if (!raceFinished.get()) { + printLock.lock(); + try { + System.out.printf("%s%s: %2d %s%n", + symbol, name, position, + generateProgressBar(position)); + } finally { + printLock.unlock(); } + } + } + + private void printFinishStatus() { + printLock.lock(); + try { + System.out.printf("%s%s: %2d %s 🏁%n", + symbol, name, position, + generateProgressBar(position)); + } finally { + printLock.unlock(); + } + } + + @Override + public String getName() { return name; } + @Override + public int getPosition() { return position; } + @Override + public String getSymbol() { return symbol; } + @Override + public void stopRacing() { stopped = true; } + } + // 兔子实现类 + static class Hare implements Racer { + private final String name; + private volatile int position; + private final String symbol; + private final Lock printLock; + private static final Random random = new Random(); + private volatile boolean stopped = false; + + public Hare(String name, Lock printLock) { + this.name = name; + this.position = 0; + this.symbol = "🐇"; + this.printLock = printLock; + } + + @Override + public void run() { + try { + while (!stopped && position < RACE_DISTANCE && !raceFinished.get()) { + // 随机睡觉(概率降低,时间缩短) + if (position > RACE_DISTANCE / 2 && random.nextDouble() < 0.15) { + printSleepStatus(); + + // 使用条件等待替代sleep + mainLock.lock(); + try { + // 等待500ms或直到比赛结束 + raceCondition.awaitNanos(500_000_000); // 500ms + } finally { + mainLock.unlock(); + } + } else { + // 兔子跳跃前进 + position += 4; + if (position > RACE_DISTANCE) position = RACE_DISTANCE; + + // 检查是否到达终点 + checkFinish(); + + // 打印状态 + printStatus(); + + // 使用条件等待替代sleep + mainLock.lock(); + try { + raceCondition.awaitNanos(50_000_000); // 50ms + } finally { + mainLock.unlock(); + } + } + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private void checkFinish() { + if (position >= RACE_DISTANCE && raceFinished.compareAndSet(false, true)) { + winner = name; + // 通知所有线程比赛结束 + mainLock.lock(); try { - Thread.sleep(100); // 兔子较快 - printHareStatus(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - break; + raceCondition.signalAll(); + } finally { + mainLock.unlock(); } + printFinishStatus(); } - }, "Hare"); + } - // 启动所有线程 - tortoiseThread.start(); - hareThread.start(); + private void printStatus() { + if (!raceFinished.get()) { + printLock.lock(); + try { + System.out.printf("%s%s: %2d %s%n", + symbol, name, position, + generateProgressBar(position)); + } finally { + printLock.unlock(); + } + } + } - try { - // 等待所有线程完成 - tortoiseThread.join(); - hareThread.join(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + private void printSleepStatus() { + printLock.lock(); + try { + System.out.printf("%s%s: 开始睡觉了😴 (当前位置: %d)%n", + symbol, name, position); + } finally { + printLock.unlock(); + } } + + private void printFinishStatus() { + printLock.lock(); + try { + System.out.printf("%s%s: %2d %s 🏁%n", + symbol, name, position, + generateProgressBar(position)); + } finally { + printLock.unlock(); + } + } + + @Override + public String getName() { return name; } + @Override + public int getPosition() { return position; } + @Override + public String getSymbol() { return symbol; } + @Override + public void stopRacing() { stopped = true; } } - private static void printTortoiseStatus() { - // 生成乌龟进度条 - String tortoiseProgress = generateProgressBar(tortoisePosition, RACE_DISTANCE); + // 赛况输出线程 + static class RaceReporter implements Runnable { + private final List racers; + private final Lock printLock; + private volatile boolean stopped = false; + + public RaceReporter(List racers, Lock printLock) { + this.racers = racers; + this.printLock = printLock; + } - System.out.println("T: " + tortoisePosition + " [" + tortoiseProgress + "]"); + @Override + public void run() { + try { + while (!stopped && !raceFinished.get()) { + printProgress(); - if (raceFinished) { - System.out.println("\n比赛结束!"); - if (winner.equals("T")) { - System.out.println("乌龟获胜!坚持不懈,终会成功!"); - } else if (winner.equals("H")) { - System.out.println("兔子获胜!速度优势明显!"); + // 使用条件等待替代sleep + mainLock.lock(); + try { + raceCondition.awaitNanos(200_000_000); // 200ms + } finally { + mainLock.unlock(); + } + } + + // 输出最终结果 + printFinalResults(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private void printProgress() { + printLock.lock(); + try { + System.out.print("\r当前进度: "); + for (Racer racer : racers) { + System.out.printf("%s%s:%2d ", + racer.getSymbol(), racer.getName(), racer.getPosition()); + } + System.out.print(" "); + } finally { + printLock.unlock(); } } - } - private static void printHareStatus() { - // 生成兔子进度条 - String hareProgress = generateProgressBar(harePosition, RACE_DISTANCE); + private void printFinalResults() { + printLock.lock(); + try { + System.out.println("\n\n====================================="); + System.out.println("🏆 比赛结束!获胜者是: " + winner + " 🏆"); + System.out.println("最终排名:"); - System.out.println("H: " + harePosition + " [" + hareProgress + "]"); + // 按位置排序 + racers.sort((r1, r2) -> Integer.compare(r2.getPosition(), r1.getPosition())); - if (raceFinished) { - System.out.println("\n比赛结束!"); - if (winner.equals("T")) { - System.out.println("乌龟获胜!坚持不懈,终会成功!"); - } else if (winner.equals("H")) { - System.out.println("兔子获胜!速度优势明显!"); + for (int i = 0; i < racers.size(); i++) { + System.out.printf("%d. %s%s - 位置: %d%n", + i + 1, racers.get(i).getSymbol(), + racers.get(i).getName(), racers.get(i).getPosition()); + } + System.out.println("====================================="); + } finally { + printLock.unlock(); } } + + public void stopReporting() { stopped = true; } } - private static String generateProgressBar(int position, int total) { - StringBuilder sb = new StringBuilder(); - int progressBarLength = 19; // 进度条长度,确保箭头'>'在最后位置时格式正确 - int filledLength = (int) ((double) position / total * progressBarLength); - - for (int i = 0; i <= progressBarLength; i++) { - if (i < filledLength) { - sb.append('-'); - } else if (i == filledLength && position < total) { - sb.append('>'); - } else if (i < progressBarLength) { - sb.append(' '); + // 生成进度条 + private static String generateProgressBar(int position) { + StringBuilder sb = new StringBuilder("["); + int barLength = 20; + int filled = (int) ((double) Math.min(position, RACE_DISTANCE) / RACE_DISTANCE * barLength); + + for (int i = 0; i < barLength; i++) { + sb.append(i < filled ? '=' : ' '); + } + sb.append(']'); + return sb.toString(); + } + + public static void main(String[] args) { + Lock printLock = new ReentrantLock(); + + printLock.lock(); + try { + System.out.println("🐢🐇 龟兔赛跑开始啦!🐇🐢"); + System.out.println("终点距离: " + RACE_DISTANCE + " 步"); + System.out.println("-------------------------------------\n"); + } finally { + printLock.unlock(); + } + + // 创建参赛者列表 + List racers = new ArrayList<>(); + racers.add(new Tortoise("一号", printLock)); + racers.add(new Tortoise("二号", printLock)); + racers.add(new Hare("一号", printLock)); + racers.add(new Hare("二号", printLock)); + + // 创建赛况报告器 + RaceReporter reporter = new RaceReporter(racers, printLock); + + // 创建线程列表 + List threads = new ArrayList<>(); + for (Racer racer : racers) { + threads.add(new Thread(racer, racer.getName())); + } + Thread reporterThread = new Thread(reporter, "Reporter"); + threads.add(reporterThread); + + // 启动所有线程 + for (Thread thread : threads) { + thread.start(); + } + + // 等待比赛结束 + mainLock.lock(); + try { + while (!raceFinished.get()) { + raceCondition.await(); } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + mainLock.unlock(); } - return sb.toString(); + // 停止所有线程 + for (Racer racer : racers) { + racer.stopRacing(); + } + reporter.stopReporting(); + + // 通知所有等待的线程 + mainLock.lock(); + try { + raceCondition.signalAll(); + } finally { + mainLock.unlock(); + } + + // 等待所有线程完成 + for (Thread thread : threads) { + try { + thread.join(1000); // 最多等待1秒 + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Hare.class b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Hare.class new file mode 100644 index 0000000000000000000000000000000000000000..2218d6a29437ce7d2d63cbfd27534dd1ad42742b Binary files /dev/null and b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Hare.class differ diff --git a/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$RaceReporter.class b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$RaceReporter.class new file mode 100644 index 0000000000000000000000000000000000000000..da22062950bcee677677ffe25cae0defcf0f78a8 Binary files /dev/null and b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$RaceReporter.class differ diff --git a/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Racer.class b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Racer.class new file mode 100644 index 0000000000000000000000000000000000000000..bab76e93c11a43e7fc2cec8ae697147ddf9bda8f Binary files /dev/null and b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Racer.class differ diff --git a/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Tortoise.class b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Tortoise.class new file mode 100644 index 0000000000000000000000000000000000000000..0e9f2a16275c55bcf28cdf4e19459083bce9757b Binary files /dev/null and b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace$Tortoise.class differ diff --git a/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace.class b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace.class new file mode 100644 index 0000000000000000000000000000000000000000..05fd94fba5ff3fdd487c349752fb654b02acb4cc Binary files /dev/null and b/src/main/java/com/example/tortoisehare/com/example/tortoisehare/TortoiseHareRace.class differ