当前位置: 首页 > 知识库问答 >
问题:

用多线程技术在Java中模拟停车场中的多个出入口

祁坚壁
2023-03-14

我目前已经创建了诸如停车场和地板之类的类来表示停车场。我使用了Floor类的ArrayList来显示停车场中的多个级别。

我想在不同的楼层有多个入口和出口,配备电梯从一层到另一层。

我应该如何处理这个问题?我希望能够在车辆同时进入和离开停车场时向停车场添加和删除多辆车辆。

在这种情况下如何使用线程和锁?

=============结构============

public class CarPark{

private ArrayList<Floor> floorList;
private ArrayList<Vehicle> vehicleList;

}

实施的方法:

  • getFloorList():ArrayList
  • 获取车辆列表():ArrayList
  • getMostSuitableFloorForVehicle(车辆):地板

>

  • addVehicle(车辆):无效

    getFreeSlots():双精度

    deleteVehicle(字符串):车辆

    获取车辆百分比():HashMap

    getOldestVehicle():车辆

    getLatestVehicle():车辆

    getVehicleById(字符串):车辆

    获取车辆字节年(String, String):ArrayList

      public class Floor implements Comparable<Floor>{
    
      private double maxCapacity;
      private double currentCapacity;
      private int currentNumberOfVehicles;
      private ArrayList<Vehicle> vehicleList;
      private ArrayList<VehicleTypes> preferredVehicleType;
      private ArrayList<VehicleTypes> possibleVehicleType;
    

    }

    实施的方法:

    • getCurrentNumberOfVehicles():int
    • getCurrentCapacity():双倍
    • getVehicleList():数组列表
    • getPreferredVehicleType():ArrayList
    • getPossibleVehicleType():ArrayList
    • GetAvailableEnumberofSlots():双精度
    • isParkingSlotsSufficient(车辆):布尔值
    • 添加车辆(Vehicle Vehicle):无效
    • getVehicleById(字符串):车辆
    • deleteVehicleByInstance(车辆):车辆
    • deleteVehicleByPlateId(字符串):车辆
    • toString():字符串
    • 比较器(地板):int

    其余的只是将被添加到停车场的车辆类别。

  • 共有2个答案

    庄元龙
    2023-03-14

    任何模拟或游戏的基础都是游戏循环。这是一个运行一定时间的循环。

    在Java中,可以使用添加到线程的Runnable来运行模拟循环。

    下面是一个可运行的示例。

    public class SimulationRunnable implements Runnable {
        
        /** Simulation run time, in minutes */
        private final int duration;
        
        private final Random random;
        
        private final SimulationView view;
        
        private final SimulationModel model;
        
        public SimulationRunnable(SimulationView view, SimulationModel model, 
                int duration) {
            this.view = view;
            this.model = model;
            this.duration = duration;
            this.random = new Random();
        }
    
        @Override
        public void run() {
            int iterations = duration * 60 * 5;
            
            for (int index = 0; index < iterations; index++) {
                // Update simulation model
                
                // We will add cars for the first 10 hours (minutes)
                
                if (index < iterations - 600) {
                    for (int jndex = 0; jndex < 5; jndex++) {
                        if (random.nextInt(10) == 5) {
                            // Add car
                        }
                    }
                }
                
                // We will remove cars for the last 10 hours (minutee)
                
                if (index > 600) {
                    for (int jndex = 0; jndex < 5; jndex++) {
                        if (random.nextInt(10) == 3) {
                            // Remove car
                        }
                    }
                }
                
                // Report status every 300 iterations
                if (index % 300 == 0) {
                    
                }
                
                // Pause simulation loop
                try {
                    Thread.sleep(200L);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
    }
    

    要开始模拟,您可以使用Runnable创建一个Thread

    new Thread(new SimulationRunnable(view, model, 12)).start();
    

    让我们假设您想要模拟一个12小时的时间段,其中车辆进出停车场。一种可能的模拟可能是:

    • 汽车进入停车场的头两个小时

    我们还假设模拟计时器以一分钟表示一小时的形式运行。因此,模拟将运行12分钟。

    我们还假设模拟循环每秒运行五次。这意味着模拟循环将每200毫秒执行一次,总共执行3600次。

    现在你所要做的就是决定每小时有多少辆车进入停车场,以及每小时有多少辆车离开停车场。利率应该非常接近。

    每小时进入停车场的汽车太多,停车场就会挤满。

    每小时进入停车场的车辆太少,停车场大部分都会空无一人。

    游戏循环将更新您的仿真模型。每隔一段时间,比如你报告停车场状态的每一个比赛小时(分钟)。

    陶山
    2023-03-14

    下面的mre使用两个线程来模拟汽车进入和离开。您可以通过更改睡眠时间来控制速率:

    import java.util.*;
    
    public class CarPark {
    
        private static final int NUM_OF_FLOOORS = 4, SLEEP = 3000;
        private final List<Floor> floorList;
    
        public CarPark() {
            floorList = Collections.synchronizedList(new ArrayList<>());
            for(int i=0; i < NUM_OF_FLOOORS; i++){
                floorList.add(new Floor(i));
            }
        }
    
        private Floor getRandomFloor() {
            Collections.shuffle(floorList);
            return floorList.get(0);
        }
    
        void simulateRandomTraffic(){
            simulateRandomEntries();
            simulateRandomExits();
        }
    
        void simulateRandomEntries(){
            new Thread(()->{
                while(true){
                    getRandomFloor().addVehicle(new Vehicle());
                    try {
                        Thread.sleep(SLEEP);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    
        void simulateRandomExits(){
            new Thread(()->{
                while(true){
                    getRandomFloor().removeRandomVehicle();
                    try {
                        Thread.sleep(SLEEP);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    
        public static void main(String[] args) {
            new CarPark().simulateRandomTraffic();
        }
    }
    
    class Floor{
    
        private final double maxCapacity = 100;
        private final List<Vehicle> vehicleList;
        private final int floorNumber;
    
        public Floor(int floorNumber) {
            this.floorNumber = floorNumber;
            vehicleList = Collections.synchronizedList(new ArrayList<>());
        }
    
        public int getCurrentNumberOfVehicles() {
            return vehicleList.size();
        }
    
        public boolean isFull(){
            return maxCapacity <= getCurrentNumberOfVehicles();
        }
    
        public boolean isEmpty(){
            return  getCurrentNumberOfVehicles() <= 0;
        }
    
        public int getFloorNumber() {
            return floorNumber;
        }
    
        private Vehicle getRandomVehicle() {
            Collections.shuffle(vehicleList);
            return vehicleList.get(0);
        }
    
        public boolean removeRandomVehicle(){
            if(isEmpty()) {
                System.err.println("Floor "+ getFloorNumber()+" is empty. Can't remove vehicle");
                return false;
            }
            return removeVehicle(getRandomVehicle());
        }
    
        public boolean addVehicle(Vehicle v){
            if(isFull()) {
                System.err.println("Floor "+ getFloorNumber()+" is full. Can't add vehicle");
                return false;
            }
            vehicleList.add(v);
            System.out.println("Floor "+ getFloorNumber()+" vehicle added ("+ getCurrentNumberOfVehicles()+"/"+maxCapacity+")");
            return true;
        }
    
        public boolean removeVehicle(Vehicle v){
            if(isEmpty()) {
                System.err.println("Floor "+ getFloorNumber()+" is empty. Can't remove vehicle");
                return false;
            }
            vehicleList.remove(v);
            System.out.println("Floor "+ getFloorNumber()+" vehicle removed ("+ getCurrentNumberOfVehicles()+"/"+maxCapacity+")");
            return true;
        }
    }
    
    class Vehicle{}
    

    下一个增强功能是停车场队列
    让第三个线程将车辆推入队列(或多个任务,每个入口一个,所有任务都由同一个线程完成)
    让模拟器进入队列()从队列中拉出并推到随机楼层。

     类似资料:
    • 问题内容: 我有一个多线程Java应用程序,该应用程序会将有关它收到的消息的信息输出到控制台以进行调试。每次应用程序收到消息时,它将在消息上调用。 我遇到的问题是,如果应用程序被消息淹没,则会打印错误信息(例如旧缓冲区信息)。这使我想知道是否存在线程问题,即多个线程一次调用该函数,而没有正确刷新缓冲区。 在我的主程序(线程)中,我有以下效果: 在我的线程中,我有以下效果: 是否有一种简单的方法可以

    • 问题内容: 在多个线程上调用Java 对象是否安全?输出会正确序列化吗? 澄清: 在我的情况下,类记录器拥有FileOutputStream引用,并且多个线程可以调用记录器写,从而格式化输出并调用FileOutputStream写。 我应该同步记录器的写方法以保证来自多个线程的消息不会混合吗? 问题答案: 不能多次打开文件,因此答案是否定的。 在看到您的编辑之后,是的,您应该在记录器中引入同步,以

    • 笔记摘要 这里介绍了java5中的线程锁技术:Lock和Condition,实现线程间的通信,其中的读锁和写锁的使用通过一个缓存系统进行了演示,对于Condition的应用通过一个阻塞队列进行演示。 线程锁技术:Lock & Condition 实现线程同步通信所属包:java.util.concurrent.locks 线程锁 说明 Synchronized 同步方法,锁对象是this;同步静态

    • 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象。 public class Test { public static void main(String[] args){ System.out.printl

    • 我有一个关于JAVA多线程的问题。 我有一个jetty webapp与grpc-流式传输-客户端。一切都很好,但我如何建立一个模型来获取流式传输数据? webapp是用jsf构建的。因为我有一个控制器,它调用一个处理程序类来启动流: 此方法简单地启动客户端和流。 检查倒计时锁存器的实现仍然缺失。但在这种情况下,这并不重要。 响应如下:onNext()-方法提供流式数据: 图像数据简单地打印在屏幕上

    • 问题内容: 在我的程序执行过程中,启动了多个线程。线程数量取决于用户定义的设置,但是它们都使用不同的变量执行相同的方法。 在某些情况下,需要在执行过程中进行清理,其中一部分是停止所有线程,尽管我不希望它们立即停止,我只是设置了一个变量来检查它们是否终止。问题在于线程停止之前最多可能需要1/2秒。但是,我需要确保所有线程都已停止,然后才能继续进行清理。清理是从另一个线程执行的,因此从技术上讲,我需要