10个线程模拟赛马,所有马就绪后才能开跑,所有马到达终点后裁判宣布赛马成绩

这是一个比较典型的多线程之间协调的一道编程题,其实主要是考察CountDownLatch和CyclicBarrier的。 要实现这个功能,可以使用 CountDownLatch 来确保所有马都就绪后再开始比赛,并使用 CyclicBarrier 来确保所有马到达终点后裁判再宣布成绩。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 /** * @author Hollis */ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; public class HorseRace { // 用于存储赛马成绩 private static List<String> results = Collections.synchronizedList(new ArrayList<>()); // 用于控制所有马同时开跑 private static CountDownLatch startLatch = new CountDownLatch(1); // 用于确保所有马到达终点后再宣布成绩 private static CyclicBarrier finishBarrier = new CyclicBarrier(10, new Runnable() { @Override public void run() { // 裁判宣布成绩 System.out.println("Race finished! Announcing results:"); for (String result : results) { System.out.println(result); } } }); public static void main(String[] args) { for (int i = 1; i <= 10; i++) { new Thread(new Horse("Horse " + i)).start(); } // 所有马就绪后开跑 try { System.out.println("All horses ready. Race starts now!"); startLatch.countDown(); // 马开跑 } catch (Exception e) { e.printStackTrace(); } } static class Horse implements Runnable { private String name; public Horse(String name) { this.name = name; } @Override public void run() { try { // 马就绪,等待开跑信号 startLatch.await(); // 马开始跑 long raceTime = (long) (Math.random() * 10000); // 模拟跑的时间 Thread.sleep(raceTime); // 马到达终点 results.add(name + " finished in " + raceTime + " ms"); // 等待其他马到达终点 finishBarrier.await(); } catch (Exception e) { e.printStackTrace(); } } } } CountDownLatch startLatch 用于控制所有马同时开跑,初始值设为 1。使用 startLatch.await() 确保所有马就绪后再开跑。使用 startLatch.countDown() 触发所有马同时开跑。 ...

March 22, 2026 · 2 min · santu

五个线程abcde,想先执行a,在执行bcd,bcd执行完后执行e如何做?

典型回答 这也是一个典型的多线程之间通信的问题, 需要控制多个线程的执行顺序,即:a ➔ (b、c、d并发完成) ➔ e 这个场景中,用 CountDownLatch 就比较合适,大致流程如下: a线程执行,执行完后 latchA.countDown() b/c/d线程在 latchA.await() 处等待,直到a执行完一起开始 b/c/d各自执行,完成后各自 latchBCD.countDown() e线程在 latchBCD.await() 处等,等bcd都完成后执行 具体代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import java.util.concurrent.CountDownLatch; public class ThreadOrderControl { public static void main(String[] args) throws InterruptedException { CountDownLatch latchA = new CountDownLatch(1); // 控制bcd等待a完成 CountDownLatch latchBCD = new CountDownLatch(3); // 控制e等待bcd完成 Thread a = new Thread(() -> { System.out.println("A start"); // do something... System.out.println("A done"); latchA.countDown(); // 通知bcd可以开始了 }); Runnable bcdTask = (String name) -> { try { latchA.await(); // 等a完成 System.out.println(name + " start"); // do something... System.out.println(name + " done"); latchBCD.countDown(); // bcd每个线程做完都countDown一次 } catch (InterruptedException e) { e.printStackTrace(); } }; Thread b = new Thread(() -> bcdTask.run("B")); Thread c = new Thread(() -> bcdTask.run("C")); Thread d = new Thread(() -> bcdTask.run("D")); Thread e = new Thread(() -> { try { latchBCD.await(); // 等bcd全部完成 System.out.println("E start"); // do something... System.out.println("E done"); } catch (InterruptedException ex) { ex.printStackTrace(); } }); // 启动所有线程 a.start(); b.start(); c.start(); d.start(); e.start(); } }

March 22, 2026 · 1 min · santu

线程池中怎么设置超时时间?一个线程如果要运行10s,怎么在1s就抛出异常

典型回答 在使用线程池时,如果希望设置线程的超时时间,并在超时后抛出异常,可以根据不同的线程池实现方式和任务管理策略进行设置。常见的Java线程池实现包括 ExecutorService 和 ScheduledExecutorService,以及如何使用 Future 和 Callable 来控制任务执行和超时。 使用Future设置超时时间 在Java中,可以使用 ExecutorService 来执行任务,并通过 Future.get(long timeout, TimeUnit unit) 方法设置超时。如果任务在指定的时间内未完成,会抛出 TimeoutException 异常。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.concurrent.*; public class ThreadPoolTimeoutExample { public static void main(String[] args) { // 创建一个线程池 ExecutorService executor = Executors.newFixedThreadPool(2); // 创建一个Callable任务 Callable<String> task = () -> { // 模拟执行10秒的任务 Thread.sleep(10000); return "Task completed"; }; // 提交任务并获取Future对象 Future<String> future = executor.submit(task); try { // 设置任务的超时时间为1秒 String result = future.get(1, TimeUnit.SECONDS); // 1秒超时 System.out.println(result); } catch (TimeoutException e) { System.out.println("Task timed out!"); future.cancel(true); // 取消任务 } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } finally { executor.shutdown(); } } } 通过 **ScheduledExecutorService** 设置任务超时 ScheduledExecutorService 是一个可以来定期或延迟执行任务的工具,他的schedule(Callable<V> callable, long delay, TimeUnit unit);方法,可以设置延迟执行,然后在延迟的时间执行中,调用cancel方法取消任务即可。 ...

March 22, 2026 · 2 min · santu

如果让你实现一个字符串的equals方法,你会如何实现?

典型回答 这个其实不是考察你背没背过String的equals方法,而是考察你实际写一个代码的时候考虑的全不全,是不是有fail-fast的想法。 很多人第一反应就是拿出来两个字符串,for循环从头开始遍历,然后一个一个字符的比较,如果这么简单,那么就没必要问了。 其实,有很多情况可以fail fast掉,不需要比较的,比如字符串长度不一致,字符串的hashcode不一致,字符串有一个为null等等。所以,正确的判断思路是: 先判断对象引用 如果两个对象是同一个引用,直接返回 true。 判断类型或 null 如果传入对象是 null 或类型不对,直接返回 false。 判断长度 字符串长度不同,肯定不相等,直接返回 false。 判断hashcode 字符串的hashcode不同,肯定不想等,直接返回 false。 逐个字符比较 遍历字符数组,逐位比较,如果有不同返回 false。 都相等 返回 true。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public boolean myEquals(String other) { // 1. 引用相等 if (this == other) { return true; } // 2. null 判断 if (other == null) { return false; } // 3. 长度判断 if (this.length() != other.length()) { return false; } // 4. hashcode判断 if (this.hashCode() != other.hashCode()) { return false; } // 5. 逐字符比较 for (int i = 0; i < this.length(); i++) { if (this.charAt(i) != other.charAt(i)) { return false; } } // 6. 全部匹配 return true; }

March 22, 2026 · 1 min · santu

留言给博主