You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java并发机场模拟:如何实现多架飞机同时访问不同登机口

代码核心缺陷
  • required_to_land方法加了synchronized修饰,导致所有飞机线程必须串行执行该方法的全部逻辑,同一时间只能有1架飞机处理降落流程,这是输出全为串行的核心原因
  • 无登机口分配逻辑,所有飞机默认调用access_gate1方法,永远只用到1号登机口
  • 错误使用Semaphore.availablePermits()做并发判断,该方法返回的是许可近似值,不能作为并发流程的判断条件;且Semaphore.acquire()本身就支持阻塞等待许可,无需提前判断
  • 4个登机口没有独立的分配、回收逻辑,资源没有被充分利用
修正方案
  1. 移除required_to_land的synchronized修饰,支持多架飞机同时发起降落请求
  2. 新增线程安全的队列管理空闲登机口,拿到Semaphore许可后自动分配空闲登机口,使用完毕后归还队列
  3. 直接调用Semaphore.acquire()阻塞等待可用许可,无需自行判断许可数量,许可数量和登机口数量一一对应
  4. 合并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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:48:00