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

Java多线程模拟停车场:解决未停车车辆误离场问题咨询

问题:未成功停车的车辆执行离场操作导致车位数量异常,如何修复?

我正在做Java多线程项目,模拟多辆车随机进出固定车位的停车场,但还没完全掌握同步概念。当前代码里,没成功进入停车场的车辆也会执行离场操作,导致车位数量异常。原代码如下:

public class CarPark
{
 
    private int slots;

    public CarPark(int slots) 
    { 
        if(slots < 0)
            slots = 0;
        this.slots = slots; 
    } 

    // Try to enter the car park
    public void tryParking(String car)
    {
        
        if (slots >= 1) // At least one free slot to park in the car park
        {
            park(car);  
        }
        else if (slots <= 0) // If there is no free slot then the car has to wait
        {
            System.out.println(car + ": is waiting for a slot. Free slots: " + slots);
        }

    }
    
    // Parking in the car park
    private void park(String car)
    { 
        slots--;
        System.out.println(car + ": is parking. Free slots: " + slots);
    } 

    // Leaving the car park
    public void leave(String car) 
    { 
        slots++;
        System.out.println(car + ": is leaving the car park. Free slots: " + slots);
    }

    public static void main( String[] args)
    {
        // 5 slots
        CarPark carpark = new CarPark(5);

        // 20 Cars
        for (int i=1; i<=20; i++) {
            Car a = new Car("Car " + i, carpark);
        }
    }
}


class Car extends Thread 
{ 
    private CarPark carpark; 

    public Car(String name, CarPark carpark) 
    { 
        super(name); 
        this.carpark = carpark;
        start(); 
    } 

    public void run() 
    {
        try {
            sleep((int)(Math.random() * 1000)); 
        } catch( InterruptedException e) { }
        
        carpark.tryParking(getName()); 
        
        try {
            sleep((int)(Math.random() * 2000)); 
        }
        catch( InterruptedException e) { } 
        
        carpark.leave(getName());
    } 
}

问题分析

核心问题有两个:

  • 未停车车辆执行离场:Car线程的run方法里,不管tryParking是否成功,都会无条件调用leave,导致没抢到车位的车也会增加slots数值,最终车位数量混乱。
  • 线程安全隐患:多个线程同时操作slots变量(读取、增减),没有同步控制,会出现竞态条件。比如多辆车同时判断slots >=1,然后都执行park,导致slots变成负数,这也是车位异常的潜在原因。

修复方案

1. 让tryParking返回停车结果

修改tryParking方法,返回布尔值表示是否成功停车,Car线程根据这个结果决定是否执行离场操作。

2. 添加同步控制,保证线程安全

给CarPark的关键方法(tryParking、leave)加上synchronized修饰,避免多线程下的竞态条件。

修改后的完整代码

public class CarPark {
 
    private int slots;

    public CarPark(int slots) { 
        if(slots < 0)
            slots = 0;
        this.slots = slots; 
    } 

    // 修改为返回boolean,标记是否成功停车
    public synchronized boolean tryParking(String car) {
        if (slots >= 1) {
            park(car);
            return true; // 成功停车,返回true
        } else {
            System.out.println(car + ": is waiting for a slot. Free slots: " + slots);
            return false; // 未停车,返回false
        }
    }
    
    private void park(String car) { 
        slots--;
        System.out.println(car + ": is parking. Free slots: " + slots);
    } 

    public synchronized void leave(String car) { 
        slots++;
        System.out.println(car + ": is leaving the car park. Free slots: " + slots);
    }

    public static void main(String[] args) {
        // 5 slots
        CarPark carpark = new CarPark(5);

        // 20 Cars
        for (int i=1; i<=20; i++) {
            new Car("Car " + i, carpark);
        }
    }
}


class Car extends Thread { 
    private CarPark carpark; 

    public Car(String name, CarPark carpark) { 
        super(name); 
        this.carpark = carpark;
        start(); 
    } 

    public void run() {
        try {
            sleep((int)(Math.random() * 1000)); 
        } catch(InterruptedException e) {
            Thread.currentThread().interrupt(); // 重置中断状态
        }
        
        // 接收停车结果,只有成功才执行离场
        boolean parkedSuccessfully = carpark.tryParking(getName()); 
        
        if (parkedSuccessfully) {
            try {
                sleep((int)(Math.random() * 2000)); 
            } catch(InterruptedException e) {
                Thread.currentThread().interrupt();
            } 
            carpark.leave(getName());
        }
    } 
}

额外优化:实现等待唤醒机制

当前的tryParking只是打印等待就结束了,实际场景中车辆应该等待直到有车位释放。可以用wait()和notifyAll()实现该逻辑,修改后的tryParking和leave方法如下:

public synchronized boolean tryParking(String car) {
    // 循环等待,直到有车位
    while (slots < 1) {
        System.out.println(car + ": is waiting for a slot. Free slots: " + slots);
        try {
            wait(); // 线程进入等待,释放锁
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false; // 被中断,放弃停车
        }
    }
    park(car);
    return true;
}

public synchronized void leave(String car) { 
    slots++;
    System.out.println(car + ": is leaving the car park. Free slots: " + slots);
    notifyAll(); // 唤醒所有等待的线程,通知有车位了
}

这样车辆会一直等待,直到有车位释放,更符合真实停车场的逻辑。

内容的提问来源于stack exchange,提问作者UniStudent27

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:30:53