SimPy队列模拟中添加if语句后程序停滞的问题求助
问题分析与解决方案
你的问题核心在于SimPy进程的事件驱动机制被破坏:
原来的代码中,yield order_queue.get()是阻塞操作,会主动让出SimPy的事件循环,让其他进程(比如生成订单的进程)有机会运行。但添加if判断后,当条件不满足时,process_orders进程会进入无限忙循环——它一直在重复执行while True和if检查,却没有任何yield语句让出控制权,导致SimPy的事件循环被完全占用,其他进程根本得不到运行机会,自然就停止反馈了。
调试时无法进入if块,大概率是因为条件一直不满足,进程卡在循环里反复检查,没有触发任何事件切换。
正确的实现方式
SimPy的设计思路是基于事件触发,而非主动轮询。你需要用SimPy的同步原语或合理的事件等待逻辑,实现“满足特定条件时才处理订单”的需求,而非自己写轮询判断。
方案1:先获取订单,再等待到指定时间处理
如果订单的start_prep是已知的,服务进程可以先获取订单,若当前时间不满足条件,就等待到start_prep时间再执行服务流程:
def process_orders(env, order_queue): while True: order = yield order_queue.get() # 如果当前时间未到start_prep,先等待到该时间点 if round(env.now, 5) < round(order.start_prep, 5): wait_time = order.start_prep - env.now yield env.timeout(wait_time) print(f"{format_time(env.now)}: {order.name} in service centers") order.exit_time = env.now # 模拟服务耗时 yield env.timeout(order.prep_time) waiting_time = order.exit_time - order.placement_time print(f"{format_time(env.now)}: {order.name} exited at {env.now:.3f} minutes. Waiting time: {waiting_time:.3f} minutes.") waiting_times.append(waiting_time)
这个方案无需额外同步对象,逻辑简洁直接:先拿订单,时间不够就等,时间到了再处理。
方案2:用Condition监听条件触发
如果需要严格“只有满足条件时才获取订单”,可以用Condition对象,在有订单入队或时间到达阈值时,唤醒服务进程检查条件:
def process_orders(env, order_queue, condition): while True: # 等待条件触发(有新订单入队 或 时间到了某个订单的start_prep) yield condition.wait() # 批量处理所有符合条件的订单 while order_queue.items and (round(env.now, 5) >= round(order_queue.items[-1].start_prep, 5)): order = order_queue.get() print(f"{format_time(env.now)}: {order.name} in service centers") order.exit_time = env.now yield env.timeout(order.prep_time) waiting_time = order.exit_time - order.placement_time print(f"{format_time(env.now)}: {order.name} exited at {env.now:.3f} minutes. Waiting time: {waiting_time:.3f} minutes.") waiting_times.append(waiting_time) # 主流程初始化 env = simpy.Environment() order_queue = simpy.Store(env) condition = simpy.Condition(env) # 生成订单的进程中,每次放入订单后通知Condition def generate_orders(env, order_queue, condition): for i in range(10): order = Order(name=f"Order {i}", placement_time=env.now, start_prep=env.now + 2, prep_time=1) yield order_queue.put(order) condition.notify() # 通知服务进程有新订单 yield env.timeout(1) # 启动进程 env.process(process_orders(env, order_queue, condition)) env.process(generate_orders(env, order_queue, condition)) env.run()
关键提醒
永远不要在SimPy进程中写没有yield的无限循环——这会直接卡死整个事件循环。所有需要等待的逻辑都必须通过yield事件(比如timeout、Store.get()、Condition.wait()等)实现,让SimPy的事件调度器有机会处理其他进程的事件。
内容的提问来源于stack exchange,提问作者sara
相关产品推荐
相关产品推荐

