电梯模拟案例分享

该文章描述了一个电梯控制调度系统的实现,系统遵循“就近”原则分配电梯,并允许乘客在进入电梯时指定目标楼层。在运行过程中,电梯可响应途中同向的乘客请求,并在等待过程中进行优化。代码示例展示了电梯状态管理、楼层任务处理以及用户交互的逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 假设你正在开发电梯的控制调度系统,请设计这个调度系统的控制逻辑,并能够响应以下场景:
    1. 客人在第n层按向上、向下的按钮
    1. 客人等待电梯到达
    1. 系统收到请求,按“就近”原则分配最快到达的电梯
    1. 客人进入电梯的时候能够指定目标楼层
    1. 在到达目标楼层途中可以响应其他同向的客人
    1. 不断轮询,有些已分配目标楼层的电梯在客人等待过程中还可以优化…
package bak;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author: ZhangHao
 * @Description: 电梯
 * 假设你正在开发电梯的控制调度系统,请设计这个调度系统的控制逻辑,并能够响应以下场景:
 * 1. 客人在第n层按向上、向下的按钮
 * 2. 客人等待电梯到达
 * 3. 系统收到请求,按“就近”原则分配最快到达的电梯
 * 4. 客人进入电梯的时候能够指定目标楼层
 * 5. 在到达目标楼层途中可以响应其他同向的客人
 * 6. 不断轮询,有些已分配目标楼层的电梯在客人等待过程中还可以优化...
 * @Date: 2023/2/8 5:57 PM
 * @Version: 1.0
 */
@Slf4j
public class Design {

    public static void main(String[] args) {
        Elevator elevator = new Elevator(null, 11, 1, 2);
        new Thread(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 用户在3层点击向上
            elevator.up(3);
        }).start();

        new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 用户在5层点击向上
            elevator.up(5);
        }).start();

        new Thread(() -> {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 用户在4层点击向下
            elevator.down(4);
        }).start();

        try {
            elevator.run();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

package bak;

import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @Author: ZhangHao
 * @Description: 电梯
 * @Date: 2023/2/8 6:39 PM
 * @Version: 1.0
 */
@Slf4j
public class Elevator {

    /**
     * 当前上还是下,null表示静止
     */
    private volatile Boolean isCurrentUp;

    /**
     * 最大楼层号
     */
    private final int maxFloor;

    /**
     * 最小楼层号
     */
    private final int minFloor;

    /**
     * 当前楼层号
     */
    private  int  currentFloor;

    /**
     * Map<当前楼层号, 当前楼层信息>
     */
    private final Map<Integer, Floor> floorMap = new HashMap<>();

    /**
     * 有用户进入或者出去的楼层号集合
     */
    private final Set<Integer> needDealFloorSet = new HashSet<>();

    public Elevator(Boolean isCurrentUp, int maxFloor, int minFloor, int  currentFloor) {
        for(int floorNum = minFloor;floorNum <= maxFloor;floorNum++) {
            floorMap.put(floorNum, new Floor(floorNum));
        }

        this.isCurrentUp = isCurrentUp;
        this.maxFloor = maxFloor;
        this.minFloor = minFloor;
        this.currentFloor = currentFloor;
    }

    public void run() throws InterruptedException {
        log.info("当前楼层号:" + currentFloor);
        while(true) {
            // 静止或者无任务处理
            if(isCurrentUp == null || needDealFloorSet.size() == 0) {
                continue;
            }

            // 当前向上,还有任务处理,上面还有任务;needDeal.get() > 0加速判断
            if(isCurrentUp && topHas(currentFloor)) {
                currentFloor++;
                log.info("电梯向上了一层,当前楼层号:" + currentFloor);
            } else if(!isCurrentUp && bottomHas(currentFloor)){
                // 当前向下,还有任务处理,下面还有任务;needDeal.get() > 0加速判断
                currentFloor--;
                log.info("电梯向下了一层,当前楼层号:" + currentFloor);
            }

            Floor floor = floorMap.get(currentFloor);
            // 有进入的任务
            if(floor.isIn()) {
                floor.setIn(false);
                log.info("用户进入,当前楼层号:" + currentFloor);
                // 模拟进入电梯,点击目标楼层
                imitate();
            }

            // 有出去的任务
            if(floor.isOut()){
                needDealFloorSet.remove(currentFloor);
                floor.setOut(false);
                log.info("用户走出,当前楼层号:" + currentFloor);
            }

            Thread.sleep(1000);
        }
    }

    /**
     * 模拟进入电梯,点击目标楼层
     */
    private void imitate() {
        // 向上时,从3层进入的用户点击了7层
        if(isCurrentUp && currentFloor == 3) {
            new Thread(() -> toFloor(7)).start();
        }

        // 向上时,从5层进入的用户点击了9层
        if(isCurrentUp && currentFloor == 5) {
            new Thread(() -> toFloor(9)).start();
        }

        // 向下后,从4层进入的用户点击了1层
        if(!isCurrentUp && currentFloor == 4) {
            new Thread(() -> toFloor(1)).start();
        }
    }

    /**
     * 点击向上按钮
     * @param currentUserFloor 用户当前楼层号
     */
    public void up(int currentUserFloor) {
        log.info("有用户点击向上,此时用户所在楼层号:" + currentUserFloor);
        Floor floor = floorMap.get(currentUserFloor);
        floor.setIn(true);
        // 初始静止或者刚向下结束,没有新的任务,开始向上
        if((isCurrentUp == null || !isCurrentUp) && needDealFloorSet.size() == 0) {
            isCurrentUp = true;
            log.info("电梯开始向上");
        }

        needDealFloorSet.add(currentUserFloor);
    }

    /**
     * 点击向下按钮
     * @param currentUserFloorNumber 用户当前楼层号
     */
    public void down(int currentUserFloorNumber) {
        log.info("有用户点击向下,此时用户所在楼层号:" + currentUserFloorNumber);
        Floor floor = floorMap.get(currentUserFloorNumber);
        floor.setIn(true);
        // 初始静止或者刚向上结束,没有新的任务,开始向下
        if((isCurrentUp == null || isCurrentUp) || needDealFloorSet.size() == 0) {
            isCurrentUp = false;
            log.info("电梯开始向下");
        }

        needDealFloorSet.add(currentUserFloorNumber);
    }

    /**
     * 点击目标楼层
     * @param toFloorNumber 目标楼层号
     */
    public void toFloor(int toFloorNumber) {
        Floor floor = floorMap.get(toFloorNumber);
        floor.setOut(true);
        needDealFloorSet.add(toFloorNumber);
        log.info("此时用户点击了想到达的楼层号:" + toFloorNumber);
    }

    /**
     * 判断上面楼层是否还有任务
     * @param currentFloorNumber 判断的基准楼层
     * @return 上面楼层是否还有任务
     */
    private boolean topHas(int currentFloorNumber) {
        for(int floorNumber = currentFloorNumber;floorNumber < maxFloor;floorNumber++) {
            if(needDealFloorSet.contains(floorNumber)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断下面楼层是否还有任务
     * @param currentFloorNumber 判断的基准楼层
     * @return 判断下面楼层是否还有任务
     */
    private boolean bottomHas(int currentFloorNumber) {
        for(int floorNumber = minFloor;floorNumber < currentFloorNumber;floorNumber++) {
            if(needDealFloorSet.contains(floorNumber)) {
                return true;
            }
        }

        return false;
    }

}

package bak;

import lombok.Data;

/**
 * @Author: ZhangHao
 * @Description: 楼层
 * @Date: 2023/2/8 6:14 PM
 * @Version: 1.0
 */
@Data
public class Floor {

    /**
     * 楼层
     */
    private int number;

    /**
     * 是否有进入
     */
    private boolean isIn = false;

    /**
     * 是否有出去
     */
    private boolean isOut = false;

    public Floor(int number) {
        this.number = number;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风铃峰顶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值