Python实现抢占式M/M/1队列时低优先级任务中断后无法恢复问题求助
问题原因分析
- 低优先级任务(type_2)的完成提示打印位置错误:
print("Job", name, "Left system at ",env.now)放在了while循环内部,每次循环(包括中断触发的单次循环结束)都会打印,导致你误以为任务已经离开系统,实际上任务还在while循环中等待重新申请资源。 - 服务计时起始点错误:
start = env.now放在了资源申请语句之前,如果任务在队列中等待了一段时间,计算已服务时长时会把等待时间也计入,导致剩余服务时间计算错误。 - 剩余服务时间调试打印错误:打印剩余服务时间时错误使用了当前时间
env.now,而非实际的剩余服务时长变量service_interval,影响调试判断。
修复后的完整代码
import random import simpy rn_seed = 10 t1_interval_arrivals = 20.0 t2_interval_arrivals = 1 t1_interval_service = 5 t2_interval_service = 20 def type_1_generator(env, interval, server): i = 0 while True: c = job(env, "type_1"+" #"+ str(i), "type_1", server, t1_interval_service) env.process(c) t = random.expovariate(1.0 / interval) yield env.timeout(t) i +=1 def type_2_generator(env, interval, server): i = 0 while True: c = job(env, "type_2"+" #"+str(i), "type_2", server, t2_interval_service) env.process(c) t = random.expovariate(1.0 / interval) yield env.timeout(t) i +=1 def job(env, name, typ , server, sr_interval): arrive = env.now print("Job", name, "Arrived at: ", arrive) service_interval = random.expovariate(1.0 / sr_interval) print("Job", name, "Total required service time: ", service_interval) if typ == "type_1": while service_interval > 1e-6: # 避免浮点数精度问题 with server.request(priority=1) as req: yield req start = env.now yield env.timeout(service_interval) service_interval = 0 print("Job", name, "Left system at: ", env.now) elif typ == "type_2": while service_interval > 1e-6: # 避免浮点数精度问题 try: with server.request(priority=2) as req: yield req start = env.now # 真正开始服务时再计时 yield env.timeout(service_interval) service_interval = 0 print("Job", name, "Left system at: ", env.now) except simpy.Interrupt: served = env.now - start service_interval -= served print(f"Job {name} Is interrupted at: {env.now}, already served: {served:.4f}, remaining service: {service_interval:.4f}") # Setup and start the simulation random.seed(rn_seed) env = simpy.Environment() # Start processes and run server = simpy.PreemptiveResource(env, capacity=1) env.process(type_1_generator(env, t1_interval_arrivals, server)) env.process(type_2_generator(env, t2_interval_arrivals, server)) env.run(until=100) # 可以指定运行时长方便查看结果
修复说明
- 调整了
start变量的赋值位置,放在yield req之后,仅统计任务实际占用资源的服务时长,保证剩余时间计算准确 - 删除了while循环内部误导性的离开提示打印,避免误判任务状态
- 修正了剩余服务时间的打印变量,同时增加了已服务时长的打印方便调试
- 用
service_interval > 1e-6替换原来的while service_interval,避免浮点数精度问题导致的死循环或者提前退出 - 给
env.run增加until参数指定模拟时长,方便查看完整的任务处理流程
内容的提问来源于stack exchange,提问作者Shey
相关产品推荐
相关产品推荐

