You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:45:01