###### 操作系统第一次作业
### 1.背景
#### 基本任务
某一层楼20层,有五部互联的电梯。基于线程思想,编写一个电梯调度程序。
#### 功能描述
- [x] 电梯应有一些按键,如:数字键、关门键、开门键、上行键、下行键、报警键等;
- [x] 有数码显示器指示当前电梯状态;
- [x] 每层楼、每部电梯门口,有上行、下行按钮、数码显示。
### 2.开发
+ 使用`python`进行开发
+ `GUI`开发使用的图形库为`pyqt5`
+ `python`版本为`3.8.1`
+ 过程式编程,电梯的状态使用一组全局变量表示,未给每部电梯设计一个类,线程间通过共享的这组全局变量进行通信,通过维护这组变量实现电梯的调度
+ 运行:在根目录下运行如下命令(安装PyQt5和运行程序)
```bash
pip install pyqt5
python Elevator.py
```
+ 或者运行打包好的.exe文件
```bash
.\Elevator.exe
```
## 具体算法
过程式编程,电梯的状态使用一组全局变量`elevator_goal`、`state`、`pause`、`floor`表示,线程间通过共享的这组全局变量进行通信,通过维护这组变量实现电梯的调度,使用一个锁`lock`保证读写不冲突。
```python
# 表示目标楼层
elevator_goal1 = set([])
elevator_goal2 = set([])
elevator_goal3 = set([])
elevator_goal4 = set([])
elevator_goal5 = set([])
elevator_goal = [elevator_goal1, elevator_goal2, elevator_goal3, elevator_goal4, elevator_goal5]
# 此数组表示电梯状态 0表示停止 1表示向上运行 -1表示向下运行
state = []
for i in range(5):
state.append(0)
# 指示该电梯是否暂停运行
pause = []
for i in range(5):
pause.append(1)
# 表示当前楼层
floor = []
for i in range(5):
floor.append(1)
# 表示楼道里的向上的请求
people_up = set([])
# 表示楼道里的向下的请求
people_down = set([])
# 5个锁
lock = []
for i in range(5):
lock.append(threading.Lock())
```
当按下内部的按钮时,相应楼层会被添加至目标楼层
```python
def set_goal(elev, flr): # 根据电梯内的按钮设定目标楼层
lock[elev - 1].acquire() # 获得锁
ex.findChild(QPushButton, "{0}+{1}".format(elev, flr)).setStyleSheet(
"QPushButton{background-image: url(background.png)}")
elevator_goal[elev - 1].add(flr)
lock[elev - 1].release() # 释放锁
```
当按下外部的按钮时,该楼层会被设为某一部电梯的任务楼层,该电梯即为距离该楼层最近的一部电梯。
```python
def set_global_goal_up(flr): # 设定楼道里上楼请求所在的楼层
ex.findChild(QPushButton, "up{0}".format(flr)).setStyleSheet("QPushButton{background-image: url(background.png)}")
people_up.add(flr)
elevator_goal[
[abs(floor[0] - flr), abs(floor[1] - flr), abs(floor[2] - flr), abs(floor[3] - flr), abs(floor[4] - flr)].index(
min(abs(floor[0] - flr), abs(floor[1] - flr), abs(floor[2] - flr), abs(floor[3] - flr),
abs(floor[4] - flr)))].add(flr)
def set_global_goal_down(flr): # 设定楼道里下楼请求所在的楼层
ex.findChild(QPushButton, "down{0}".format(flr)).setStyleSheet("QPushButton{background-image: url(background.png)}")
people_down.add(flr)
elevator_goal[
[abs(floor[0] - flr), abs(floor[1] - flr), abs(floor[2] - flr), abs(floor[3] - flr), abs(floor[4] - flr)].index(
min(abs(floor[0] - flr), abs(floor[1] - flr), abs(floor[2] - flr), abs(floor[3] - flr),
abs(floor[4] - flr)))].add(flr)
```
上面两段代码是一样的,外部按钮的上楼和下楼区别在于,比如当外部按钮的▲10和▼10都被按下,而有一部电梯的升降路线为9->10->11则外部按钮的▲10会被清除而▼10会继续保持。此算法在函数`check_and_change_floor`中。
```python
...
# 从外部等候楼层中移除该层
if state[int - 1] == -1:
ex.findChild(QPushButton, "down{0}".format(floor[int - 1])).setStyleSheet(
"QPushButton{}") # 移除标识
if state[int - 1] == 1:
ex.findChild(QPushButton, "up{0}".format(floor[int - 1])).setStyleSheet(
"QPushButton{}") # 移除标识
...
...
if state[int - 1] == 1:
people_up.discard((floor[int - 1])) # 移除楼层
if state[int - 1] == -1:
people_down.discard(floor[int - 1]) # 移除楼层
...
```
五个线程每秒执行一次`check_and_change_floor`,进行更改当前楼层的操作,主要的算法也包含其中。
具体流程为先根据状态(上行、静止、下行)改变当前所在楼层,根据改变后的楼层从任务列表里去除相应楼层并且熄灭相应的按钮,再根据任务列表和当前所在的楼层改变电梯的状态。然后在睡眠1s之后,继续重复此流程。为每个电梯都安排一个这样的线程。
```python
def check_and_change_floor(int):
while (1):
if pause[int - 1] == 1:
# 改变电梯楼层
lock[int - 1].acquire() # 加锁
if state[int - 1] == 0:
pass
else:
if state[int - 1] == -1:
floor[int - 1] = floor[int - 1] - 1
else:
floor[int - 1] = floor[int - 1] + 1
ex.findChild(QLCDNumber, "{0}".format(int)).display(floor[int - 1])
ex.findChild(QPushButton, "{0}+{1}".format(int, floor[int - 1])).setStyleSheet(
"QPushButton{}") # 去掉该层的标识
# 从外部等候楼层中移除该层
if state[int - 1] == -1:
ex.findChild(QPushButton, "down{0}".format(floor[int - 1])).setStyleSheet(
"QPushButton{}") # 移除标识
if state[int - 1] == 1:
ex.findChild(QPushButton, "up{0}".format(floor[int - 1])).setStyleSheet(
"QPushButton{}") # 移除标识
if state[int - 1] == 1:
if (floor[int - 1] in elevator_goal[int - 1]) or (floor[int - 1] in people_up):
lock[int - 1].release()
ex.findChild(QPushButton, "open{0}".format(int)).setStyleSheet(
"QPushButton{background-image: url(open.png)}")
time.sleep(2)
ex.findChild(QPushButton, "open{0}".format(int)).setStyleSheet(
"QPushButton{}")
lock[int - 1].acquire()
if state[int - 1] == -1:
if (floor[int - 1] in elevator_goal[int - 1]) or (floor[int - 1] in people_down):
lock[int - 1].release()
ex.findChild(QPushButton, "open{0}".format(int)).setStyleSheet(
"QPushButton{background-image: url(open.png)}")
time.sleep(2)
ex.findChild(QPushButton, "open{0}".format(int)).setStyleSheet(
"QPushButton{}")
lock[int - 1].acquire()
if state[int - 1] == 1:
people_up.discard((floor[int - 1])) # 移除楼层
if state[int - 1] == -1:
people_down.discard(floor[int - 1]) # 移除楼层
elevator_goal[int - 1].discard(floor[int - 1]) # 从要达到的目标楼层中移除该层
# ----------------------状态改变的算法---------------------- #
if state[int - 1] == -1: # 如果当前状态是向下
if len(list(elevator_goal[int - 1])) == 0:
state[int - 1] = 0
if (len(list(elevator_goal[int - 1])) != 0) and (
min(list(elevator_goal[int - 1])) > floor[int - 1]):
state[int - 1] = 1
if state[int - 1] == 1: # 如果当前状态是向上
if len(list(eleva
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
基本任务:某一层楼20层,有五部互联的电梯。基于线程思想,编写一个电梯调度程序。 功能描述:1、电梯应有一些按键,如:数字键、关门键、开门键、上行键、下行键、报警键等;2、有数码显示器指示当前电梯状态;3、每层楼、每部电梯门口,有上行、下行按钮、数码显示。
资源推荐
资源详情
资源评论
收起资源包目录
100012820-基于Python实现(GUI)电梯调度系统.zip (16个子文件)
elevator-dispatching
LICENSE 1KB
.idea
Elevator-Dispatching-Demo.iml 284B
vcs.xml 180B
workspace.xml 9KB
misc.xml 185B
inspectionProfiles
profiles_settings.xml 174B
modules.xml 302B
img
184514.png 122KB
352f36e67.png 30KB
27、24.png 32KB
3152e706e67.png 76KB
Elevator.py 12KB
background.png 325B
open.png 3KB
README.md 13KB
demo.mp4 4.85MB
共 16 条
- 1
资源评论
神仙别闹
- 粉丝: 4130
- 资源: 7483
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功