使用CountDownLatch设计单跑道航班调度的代码问题排查求助
单跑道航班调度代码问题排查与修正
核心问题分析
你用CountDownLatch实现互斥完全搞错了它的用途:
CountDownLatch是一次性组件:计数器减到0后,所有等待的线程都会被唤醒,但计数器不会再恢复,后续调用countDown()也无法让它回到初始值。- 你的代码里初始计数设为1,所有线程调用
latch.await()后都会永久阻塞——因为没有任何线程先调用countDown()把计数器降到0,程序直接卡死。
正确实现方案
单跑道互斥的本质是同一时刻仅允许一个线程访问资源,适合用Semaphore(信号量,许可数设为1)或ReentrantLock实现。以下是用Semaphore修正后的代码:
import java.util.concurrent.Semaphore; public class LandingArrivingFlights { private static final int NUM_FLIGHTS = 5; private static final int RUNWAY_CAPACITY = 1; public static void main(String[] args) { // 信号量设置1个许可,实现互斥访问 Semaphore runwaySemaphore = new Semaphore(RUNWAY_CAPACITY); for (int i = 0; i < NUM_FLIGHTS; i++) { Flight flight = new Flight(i + 1, runwaySemaphore); new Thread(flight).start(); } } private static class Flight implements Runnable { private int flightNum; private Semaphore runwaySemaphore; public Flight(int flightNum, Semaphore runwaySemaphore) { this.flightNum = flightNum; this.runwaySemaphore = runwaySemaphore; } public void run() { try { // 获取跑道许可,无许可则等待 runwaySemaphore.acquire(); // 模拟航班起降操作 if (flightNum % 2 == 0) { System.out.println("Flight " + flightNum + " is taking off."); } else { System.out.println("Flight " + flightNum + " is landing."); } // 模拟实际起降耗时,让调度效果更直观 Thread.sleep(1000); // 释放跑道许可,供其他航班使用 runwaySemaphore.release(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } } } }
关键说明
Semaphore的acquire()方法会尝试获取许可,无可用许可时线程阻塞;release()会释放许可,唤醒等待队列中的线程。- 新增
Thread.sleep(1000)模拟实际起降的耗时,能清晰看到同一时刻只有一个航班在使用跑道。 - 将内部类名从
Runway改为Flight,更符合线程代表航班的语义。
内容的提问来源于stack exchange,提问作者Karthikeyan
相关产品推荐
相关产品推荐

