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

Java多线程模拟停车场多层多出入口车辆进出实现方案咨询

停车场并发功能设计实现方案

一、基础结构适配(泛型/出入口/电梯改造)

首先完成基础逻辑扩展,匹配需求:

  • 泛型补全:原有ArrayList全部补全对应泛型,比如CarPark的floorList定义为ArrayList<Floor>,Floor的vehicleList定义为ArrayList<Vehicle>,避免类型转换异常。
  • 多出入口配置:在Floor类新增两个集合属性List<Entrance> entrances、List<Exit> exits,存储当前楼层的出入口信息,Entrance/Exit类可扩展开放状态、排队长度、所属楼层等属性。
  • 电梯功能实现:单独封装ElevatorScheduler电梯调度器(单例模式,支持多台电梯并行调度),内部维护待处理请求队列,用独立线程异步处理不同楼层的车辆升降请求,车辆进出场需要使用电梯时,直接提交请求到调度队列即可。

二、并发安全实现(线程与锁机制)

原有代码使用的ArrayList、HashMap都是非线程安全类,多线程并发操作会出现并发修改异常、余位统计错误、同一车位重复分配等问题,需要从以下维度改造:

2.1 线程安全集合替换

所有集合类优先使用JUC包下的线程安全实现:

  • 读多写少的列表(楼层列表、车辆列表、出入口列表)全部替换为CopyOnWriteArrayList,无需额外加读锁即可保证并发读安全。
  • 统计类HashMap替换为ConcurrentHashMap,避免哈希表扩容、修改时的并发冲突。

2.2 细粒度锁设计

避免使用全局锁降低并发度,采用分层细粒度锁:

  • 每个Floor实例单独持有一个ReentrantLock锁,所有修改楼层数据的操作(新增/删除车辆、修改容量统计)都需要先获取当前楼层的锁,不同楼层的操作完全并行,大幅提升吞吐。
  • 电梯调度器单独加锁,避免多楼层同时提交请求时的电梯状态冲突。

2.3 并发操作校验逻辑

为了避免读操作拿到的余位数据和加锁后的实际数据不一致,所有写操作需要做二次校验:

  • 车辆进场:先无锁查询匹配的目标楼层,获取目标楼层锁后,再次调用isParkingSlotsSufficient校验余位,校验通过再执行新增操作,最后释放锁。
  • 车辆出场:先无锁查询车辆所在楼层,获取对应楼层锁后,二次校验车辆确实在当前楼层的车辆列表中,再执行删除操作,最后释放锁。

三、核心代码改造示例

改造后的Floor类(加锁+线程安全集合)

public class Floor implements Comparable<Floor>{
    // 楼层级细粒度锁
    private final ReentrantLock floorLock = new ReentrantLock();
    private double maxCapacity;
    private double currentCapacity;
    private int currentNumberOfVehicles;
    // 替换为线程安全集合并补全泛型
    private CopyOnWriteArrayList<Vehicle> vehicleList;
    private CopyOnWriteArrayList<VehicleTypes> preferredVehicleType;
    private CopyOnWriteArrayList<VehicleTypes> possibleVehicleType;
    private CopyOnWriteArrayList<Entrance> entrances;
    private CopyOnWriteArrayList<Exit> exits;
    private int floorNum;

    // 改造新增车辆方法,加锁保证原子性
    public boolean addVehicle(Vehicle vehicle) {
        floorLock.lock();
        try {
            // 二次校验余位
            if (!isParkingSlotsSufficient(vehicle)) {
                return false;
            }
            vehicleList.add(vehicle);
            // 同步更新容量统计
            currentCapacity += vehicle.getOccupiedSpace();
            currentNumberOfVehicles++;
            vehicle.setParkedFloor(this);
            return true;
        } finally {
            // 确保锁一定会释放
            floorLock.unlock();
        }
    }

    // 改造删除车辆方法
    public Vehicle deleteVehicleByPlateId(String plateId) {
        floorLock.lock();
        try {
            Vehicle target = getVehicleById(plateId);
            if (target == null) {
                return null;
            }
            vehicleList.remove(target);
            currentCapacity -= target.getOccupiedSpace();
            currentNumberOfVehicles--;
            return target;
        } finally {
            floorLock.unlock();
        }
    }

    // 其余原有方法无需大幅调整,所有修改类属性的方法都按照上述逻辑加锁即可
}

改造后的CarPark类(支持并发操作+电梯调度)

public class CarPark{
    // 替换为线程安全集合并补全泛型
    private CopyOnWriteArrayList<Floor> floorList;
    private CopyOnWriteArrayList<Vehicle> vehicleList;
    // 电梯调度器单例
    private final ElevatorScheduler elevatorScheduler = ElevatorScheduler.getInstance();

    // 改造车辆进场方法
    public boolean addVehicle(Vehicle vehicle) {
        Floor targetFloor = getMostSuitableFloorForVehicle(vehicle);
        if (targetFloor == null) {
            return false;
        }
        // 调用楼层加锁的新增方法
        boolean addSuccess = targetFloor.addVehicle(vehicle);
        if (addSuccess) {
            vehicleList.add(vehicle);
            // 提交电梯调度请求,异步执行
            elevatorScheduler.submitRequest(new ElevatorRequest(vehicle, 1, targetFloor.getFloorNum()));
        }
        return addSuccess;
    }

    // 改造车辆出场方法
    public Vehicle deleteVehicle(String plateId) {
        Vehicle target = getVehicleById(plateId);
        if (target == null) {
            return null;
        }
        Floor parkedFloor = target.getParkedFloor();
        Vehicle deleted = parkedFloor.deleteVehicleByPlateId(plateId);
        if (deleted != null) {
            vehicleList.remove(deleted);
            elevatorScheduler.submitRequest(new ElevatorRequest(deleted, parkedFloor.getFloorNum(), 1));
        }
        return deleted;
    }

    // 其余原有统计方法都是读操作,使用线程安全集合无需额外加锁即可直接使用
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 11:36:07