如何将Python单理发师版睡眠理发师问题实现扩展为多理发师版本?
没问题!把单理发师的睡眠理发师问题扩展成多理发师版本其实核心是把理发师从单个实例改成一个理发师池,同时调整顾客的逻辑——当顾客来的时候,优先找空闲的理发师,找不到的话再去等候椅排队。下面我给你一步步拆解实现思路,再附上完整的Python 2.7代码:
核心改动要点
- 不再用单个变量存储理发师状态,而是创建一个理发师列表,每个理发师拥有自己的空闲标记和唤醒事件(
Event) - 新增顾客的「理发师匹配逻辑」:顾客到达后先遍历理发师列表,找到第一个空闲的就唤醒他;如果所有理发师都忙,再检查等候椅是否有空位
- 理发师的工作循环调整:理完一位顾客后,重新标记自己为空闲,等待下一次被唤醒
完整多理发师实现代码
from threading import Thread, Lock, Event import time import random from sys import exit # 全局配置 NUM_BARBERS = 2 # 理发师数量 WAITING_CHAIRS = 3 # 等候椅数量 customerIntervalMin = 1 # 顾客最小到达间隔(缩短方便测试) customerIntervalMax = 5 haircutDurationMin = 3 haircutDurationMax = 8 # 全局锁和共享状态 waiting_room_lock = Lock() waiting_customers = [] # 等候的顾客队列 barbers = [] # 理发师列表 class Barber(Thread): def __init__(self, barber_id): Thread.__init__(self) self.barber_id = barber_id self.is_free = True self.customer_ready = Event() # 用于唤醒理发师的事件 self.current_customer = None self.daemon = True print(f"理发师 #{self.barber_id} 准备就绪,等待顾客...") def run(self): while True: # 等待顾客唤醒 self.customer_ready.wait() # 开始理发 if self.current_customer: print(f"理发师 #{self.barber_id} 开始为顾客 {self.current_customer} 理发") haircut_time = random.randint(haircutDurationMin, haircutDurationMax) time.sleep(haircut_time) print(f"理发师 #{self.barber_id} 完成顾客 {self.current_customer} 的理发,耗时 {haircut_time} 秒") # 理发完成,标记自己为空闲 self.is_free = True self.current_customer = None self.customer_ready.clear() # 重置事件,等待下一个顾客 # 检查等候区是否有顾客,如果有就叫下一个 with waiting_room_lock: if waiting_customers: next_customer = waiting_customers.pop(0) self.current_customer = next_customer self.is_free = False print(f"理发师 #{self.barber_id} 叫等候区的顾客 {next_customer} 过来理发") self.customer_ready.set() class Customer(Thread): def __init__(self, customer_id): Thread.__init__(self) self.customer_id = customer_id self.daemon = True def run(self): print(f"顾客 {self.customer_id} 来到理发店") with waiting_room_lock: # 先找空闲的理发师 free_barber = None for barber in barbers: if barber.is_free: free_barber = barber break if free_barber: # 找到空闲理发师,直接过去 free_barber.current_customer = self.customer_id free_barber.is_free = False print(f"顾客 {self.customer_id} 找到空闲的理发师 #{free_barber.barber_id}") free_barber.customer_ready.set() else: # 所有理发师都忙,检查等候椅 if len(waiting_customers) < WAITING_CHAIRS: waiting_customers.append(self.customer_id) print(f"顾客 {self.customer_id} 进入等候区,当前等候人数: {len(waiting_customers)}") else: # 等候椅满了,顾客离开 print(f"顾客 {self.customer_id} 发现等候椅已满,离开理发店") def customer_generator(): """生成顾客的线程""" customer_id = 1 while True: # 随机间隔生成顾客 interval = random.randint(customerIntervalMin, customerIntervalMax) time.sleep(interval) Customer(customer_id).start() customer_id += 1 if __name__ == "__main__": # 初始化理发师线程 for i in range(NUM_BARBERS): barber = Barber(i+1) barbers.append(barber) barber.start() # 启动顾客生成器 customer_generator() # 主线程保持运行 try: while True: time.sleep(1) except KeyboardInterrupt: print("\n理发店打烊啦!") exit(0)
关键逻辑说明
- 理发师类:每个理发师有独立的
is_free状态和customer_ready事件,确保多个理发师之间的状态不会互相干扰 - 顾客匹配:顾客优先找空闲理发师,避免不必要的排队;只有当所有理发师都忙时才进入等候区
- 等候区调度:理发师理完发后会主动检查等候区,如果有顾客就直接叫号,不需要额外的调度线程
- 线程安全:所有操作共享资源(等候队列、理发师状态)的地方都用
Lock保护,避免竞态条件
你可以通过调整NUM_BARBERS和WAITING_CHAIRS参数来测试不同的场景,比如增加理发师数量或者等候椅数量,看看顾客的流动情况变化~
内容的提问来源于stack exchange,提问作者Marc Prior
相关产品推荐
相关产品推荐

