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
相关产品推荐
相关产品推荐

