Python中幼儿园级别电梯调度模拟实验
一、前言
每天下班回家都能看到电梯,所以很想弄懂电梯是怎么实现自动调度的,由于本人python才疏学浅,本次博客偏新手向
PS:测试版本,以后会不断完善
二、版本说明
版本 | 更新日期 |
---|---|
1.0_beta | 2022-02-14 |
1.1_rc | 2022-02-15 |
三、1.0beta版本代码逻辑
- 创建电梯A,电梯B两个线程
- 获取去往的楼层,限制最大楼层为10
- 根据电梯当前楼层与去往楼层的距离,选择调用电梯A,或者电梯B
- 使用线程中的互斥锁,顺序调度
3.1、1.0beta版本代码
具体实现代码如下:
import logging, time
from threading import Lock, Thread
fomatter = logging.Formatter(' %(levelname)s %(asctime)s - %(funcName)s - %(thread)s [%(message)s]')
# 创建日志器对象
logger = logging.getLogger()
# 日志级别总开关
logger.setLevel("INFO")
# 创建控制台hander
console_hander = logging.StreamHandler()
# 创建控制台hander日志等级
console_hander.setLevel(level='INFO')
# 添加日志格式对象
console_hander.setFormatter(fomatter)
logger.addHandler(console_hander)
height_A = 0
height_B = 0
def diantiA(lock, select_height, staus):
if staus:
global height_A
lock.acquire()
logger.info('电梯A开始运行')
while True:
if select_height > height_A:
logger.info(f'电梯A开始上升,当前电梯楼层为{height_A},去往{select_height}')
height_A += 1
time.sleep(0.25)
if height_A == select_height:
logger.info('电梯A已到站')
lock.release()
break
else:
logger.info(f'电梯A开始下降,当前电梯楼层为{height_A},去往{select_height}')
height_A -= 1
time.sleep(0.25)
if height_A == select_height:
logger.info('电梯A已到站')
lock.release()
break
else:
logger.info('电梯B以完成任务,电梯A不接受')
def diantiB(lock, select_height, staus):
if staus:
global height_B
lock.acquire()
logger.info('电梯B开始运行')
while True:
if select_height > height_B:
logger.info(f'电梯B开始上升,当前电梯楼层为{height_B},去往{select_height}')
height_B += 1
time.sleep(0.25)
if height_B == select_height:
logger.info('电梯B已到站')
lock.release()
break
else:
logger.info(f'电梯B开始下降,当前电梯楼层为{height_B},去往{select_height}')
height_B -= 1
time.sleep(0.25)
if height_B == select_height:
logger.info('电梯B已到站')
lock.release()
break
else:
logger.info('电梯A以完成任务,电梯B不接受')
def main():
lock = Lock()
while True:
staus = True
try:
print(f'电梯A当前高度{height_A},电梯B当前高度{height_B}')
select_dianti = int(input('请输入楼层:'))
if select_dianti > 10:
logger.error('输入的电梯超过楼层高度,最高为10层,请重新输入')
continue
else:
resultA = abs(select_dianti - height_A)
resultB = abs(select_dianti - height_B)
da = Thread(target=diantiA, args=(lock, select_dianti, staus))
db = Thread(target=diantiB, args=(lock, select_dianti, staus))
if resultA >= resultB:
staus = True
db.start()
db.join()
staus = False
else:
staus = True
da.start()
da.join()
staus = False
except Exception as e:
logger.error(f'input wrong{e}')
continue
if __name__ == '__main__':
main()
四、1.1rc版本代码逻辑
- 创建电梯A,电梯B两个线程
- 获取用户当前所在的楼层,去往的楼层,限制两种楼层最大为10
- 根据电梯当前楼层与去往楼层的距离,选择调用电梯A,或者电梯B,AB初始楼层一致时,默认会调度电梯B
- 如果用户所在的楼层大于电梯当前的楼层,执行上升操作,反之则电梯下降
- 使用线程中的互斥锁,顺序调度
4.1、1.1rc版本代码
全部代码如下:
import logging, time
from threading import Lock, Thread
fomatter = logging.Formatter(' %(levelname)s %(asctime)s - %(funcName)s - %(thread)s [%(message)s]')
# 创建日志器对象
logger = logging.getLogger()
# 日志级别总开关
logger.setLevel("INFO")
# 创建控制台hander
console_hander = logging.StreamHandler()
# 创建控制台hander日志等级
console_hander.setLevel(level='INFO')
# 添加日志格式对象
console_hander.setFormatter(fomatter)
logger.addHandler(console_hander)
height_A = 0
height_B = 0
def diantiA(lock, select_height, staus, target):
if staus:
global height_A
lock.acquire()
logger.info('电梯A开始运行')
while True:
# 如果用户所在的楼层大于电梯当前的楼层,执行上升操作
if select_height > height_A:
logger.info(f'电梯A开始上升,准备搭载乘客,当前电梯楼层为{height_A}')
height_A += 1
time.sleep(0.25)
if height_A == select_height:
logger.info('电梯A已到站,开始搭载乘客')
logger.info(f'去往:{target}')
while True:
# 判断电梯当前楼层与目标楼层的大小,如果目标楼层大于当前楼层,执行上升操作,反之执行下降操作
if target > height_A:
height_A += 1
logger.info(f'电梯A搭载乘客中,当前电梯楼层为{height_A}')
time.sleep(0.25)
if height_A == target:
logger.info('电梯A成功到达目标楼层')
break
else:
height_A -= 1
logger.info(f'电梯A搭载乘客中,当前电梯楼层为{height_A}')
time.sleep(0.25)
if height_A == target:
logger.info("电梯A成功到达目标楼层")
break
lock.release()
break
else:
logger.info(f'电梯A开始下降,准备搭载乘客,当前电梯楼层为{height_A}')
height_A -= 1
time.sleep(0.25)
if height_A == select_height:
logger.info(f'电梯A已到站,开始搭载乘客,目标楼层为{target}')
while True:
# 判断电梯当前楼层与目标楼层的大小,如果目标楼层大于当前楼层,执行上升操作,反之执行下降操作
if target > height_A:
height_A += 1
logger.info(f'电梯A搭载乘客中,当前电梯楼层为{height_A}')
time.sleep(0.25)
if height_A == target:
logger.info('电梯A成功到达目标楼层')
break
else:
height_A -= 1
logger.info(f'电梯A搭载乘客中,当前电梯楼层为{height_A}')
time.sleep(0.25)
if height_A == target:
logger.info("电梯A成功到达目标楼层")
break
lock.release()
break
else:
logger.info('电梯B以完成任务,电梯A不接受')
def diantiB(lock, select_height, staus, target):
if staus:
global height_B
lock.acquire()
logger.info('电梯B开始运行')
while True:
# 如果用户所在的楼层大于电梯当前的楼层,执行上升操作
if select_height > height_B:
logger.info(f'电梯B开始上升,准备搭载乘客')
height_B += 1
time.sleep(0.25)
if height_B == select_height:
logger.info('电梯B已到站,开始搭载乘客,目标楼层为{target}')
while True:
# 判断电梯当前楼层与目标楼层的大小,如果目标楼层大于当前楼层,执行上升操作,反之执行下降操作
if target > height_B:
height_B += 1
logger.info(f'电梯B搭载乘客中,当前电梯楼层为{height_B}')
time.sleep(0.25)
if height_B == target:
logger.info('电梯B成功到达目标楼层')
break
else:
height_B -= 1
logger.info(f'电梯B搭载乘客中,当前电梯楼层为{height_B}')
time.sleep(0.25)
if height_B == target:
logger.info('电梯B成功到达目标楼层')
break
lock.release()
break
else:
logger.info(f'电梯B开始下降,当前电梯楼层为{height_B}')
height_B -= 1
time.sleep(0.25)
if height_B == select_height:
logger.info('电梯B已到站')
logger.info(f'去往:{target}')
while True:
# 判断电梯当前楼层与目标楼层的大小,如果目标楼层大于当前楼层,执行上升操作,反之执行下降操作
if target > height_B:
height_B += 1
logger.info(f'电梯B搭载乘客中,当前电梯楼层为{height_B}')
time.sleep(0.25)
if height_B == target:
logger.info('电梯B成功到达目标楼层')
break
else:
height_B -= 1
logger.info(f'电梯B搭载乘客中,当前电梯楼层为{height_B}')
time.sleep(0.25)
if height_B == target:
logger.info('电梯B成功到达目标楼层')
break
lock.release()
break
else:
logger.info('电梯A以完成任务,电梯B不接受')
def main():
lock = Lock()
while True:
staus = True
try:
print(f'电梯A当前高度{height_A},电梯B当前高度{height_B}')
select_dianti = int(input('当前电梯楼层为:'))
target = int(input('去往楼层为:'))
if select_dianti > 10 or target > 10:
logger.error('输入的电梯超过楼层高度,最高为10层,请重新输入')
continue
else:
resultA = abs(select_dianti - height_A)
resultB = abs(select_dianti - height_B)
da = Thread(target=diantiA, args=(lock, select_dianti, staus, target))
db = Thread(target=diantiB, args=(lock, select_dianti, staus, target))
if resultA >= resultB:
staus = True
db.start()
db.join()
staus = False
else:
staus = True
da.start()
da.join()
staus = False
except Exception as e:
logger.error(f'input wrong{e}')
continue
if __name__ == '__main__':
main()