Java并发机场模拟:如何实现多架飞机同时访问不同登机口
代码核心缺陷
required_to_land方法加了synchronized修饰,导致所有飞机线程必须串行执行该方法的全部逻辑,同一时间只能有1架飞机处理降落流程,这是输出全为串行的核心原因- 无登机口分配逻辑,所有飞机默认调用
access_gate1方法,永远只用到1号登机口 - 错误使用
Semaphore.availablePermits()做并发判断,该方法返回的是许可近似值,不能作为并发流程的判断条件;且Semaphore.acquire()本身就支持阻塞等待许可,无需提前判断 - 4个登机口没有独立的分配、回收逻辑,资源没有被充分利用
修正方案
- 移除
required_to_land的synchronized修饰,支持多架飞机同时发起降落请求 - 新增线程安全的队列管理空闲登机口,拿到Semaphore许可后自动分配空闲登机口,使用完毕后归还队列
- 直接调用
Semaphore.acquire()阻塞等待可用许可,无需自行判断许可数量,许可数量和登机口数量一一对应 - 合并4个重复的登机口处理方法,通过传参实现不同登机口的逻辑复用
修正后完整代码
package assignment_self; import java.util.Arrays; import java.util.Queue; import java.util.Random; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Semaphore; import java.util.logging.Level; import java.util.logging.Logger; class Runway{ static Semaphore capacity = new Semaphore(4); // 管理空闲登机口的线程安全队列 Queue<Integer> freeGates = new ConcurrentLinkedQueue<>(Arrays.asList(1,2,3,4)); // 去掉synchronized,允许多个飞机同时发起请求 void required_to_land(Plane plane) throws InterruptedException { System.out.println("Plane "+ plane.id + " is requesting to land!"); System.out.println("Available gates left: " + capacity.availablePermits()); try { Thread.sleep(1000); } catch (InterruptedException ex) { Logger.getLogger(Runway.class.getName()).log(Level.SEVERE, null, ex); } access_runway(plane); } void access_runway(Plane plane) throws InterruptedException { // acquire会自动阻塞,直到有可用许可,无需提前判断 capacity.acquire(); System.out.println("Plane "+ plane.id+ " had accessed the runway!"); try { Thread.sleep(new Random().nextInt(5)*1000); } catch (InterruptedException ex) { Logger.getLogger(Runway.class.getName()).log(Level.SEVERE, null, ex); } // 取空闲登机口 int gateId = freeGates.poll(); accessGate(plane, gateId); } // 合并重复的登机口方法,通过参数区分登机口 void accessGate(Plane plane, int gateId) throws InterruptedException { System.out.println("Plane " + plane.id+ " is landing at gate " + gateId + "!"); Thread.sleep(1000); System.out.println("Plane " + plane.id+ " is letting passengers down!"); Thread.sleep(1000); System.out.println("Plane "+ plane.id+ " is leaving gate " + gateId + "!"); // 归还登机口到空闲队列 freeGates.offer(gateId); capacity.release(); } } class Plane extends Thread{ Runway runway; int id; Plane(int id, Runway runway) { this.id = id; this.runway = runway; } @Override public void run() { try { runway.required_to_land(this); } catch (InterruptedException ex) { Logger.getLogger(Plane.class.getName()).log(Level.SEVERE, null, ex); } } } public class Assignment_self { public static void main(String[] args) { Runway runway= new Runway(); for(int i=1 ; i<= 10 ; i++) { Plane p = new Plane(i, runway); p.start(); } } }
运行上述代码后,输出逻辑就会和你期望的一致,支持多架飞机同时占用不同登机口,登机口释放后会自动分配给等待的飞机。
内容的提问来源于stack exchange,提问作者user15330212
相关产品推荐
相关产品推荐

