Python双教师线程队列的实验作业模拟实现求助
解决多教师并行批改作业的模拟实现问题
你的核心问题是原代码用全局锁强制教师串行工作,且未实现学生排队分配给空闲教师的逻辑。下面是基于queue.Queue实现的正确方案,支持2名教师并行批改,学生自动排队,优先分配给空闲教师:
修改后的完整代码
import threading import queue import time import random from queue import Queue class Student: def __init__(self, id) -> None: self.MIN_TEST_EXECUTION_TIME = 1 self.MAX_TEST_EXECUTION_TIME = 5 self._student_id = id self.test_execution_time = random.randint( self.MIN_TEST_EXECUTION_TIME, self.MAX_TEST_EXECUTION_TIME) self._test_result = False def get_id(self): return self._student_id def set_result(self, result: bool): if not result: print(f"学生 {self.get_id()} 需要重做") self.test_execution_time = random.randint( self.MIN_TEST_EXECUTION_TIME, self.MAX_TEST_EXECUTION_TIME) return self._test_result = result def take_test(self): print(f"学生 {self.get_id()} 开始做作业") time.sleep(self.test_execution_time) print(f"学生 {self.get_id()} 完成作业,等待批改") def get_result(self): return self._test_result class Students: def __init__(self): self._students = [] def _append_student(self, student_id): self._students.append(Student(student_id)) def create_group(self, students_amount): for _ in range(students_amount): self._append_student(f'#{_+1}') # 学号从#1开始更直观 def get_group(self): return self._students class Teacher: def __init__(self, name) -> None: self.name = name self.MIN_TEST_CHECKING_TIME = 1 self.MAX_TEST_CHECKING_TIME = 5 def check_test(self, student: Student): check_time = random.randint(self.MIN_TEST_CHECKING_TIME, self.MAX_TEST_CHECKING_TIME) print(f"教师 {self.name} 开始批改学生 {student.get_id()} 的作业") time.sleep(check_time) print(f"教师 {self.name} 完成学生 {student.get_id()} 的作业批改") result = random.choice([True, False]) student.set_result(result) class Exam: def __init__(self, teachers: list, tested: Students) -> None: self.teachers = teachers self.students = tested.get_group() self.submission_queue = Queue() # 作业提交队列 self.completed_students = 0 self.total_students = len(self.students) self.lock = threading.Lock() # 统计完成人数的锁 def teacher_work(self, teacher): # 教师持续从队列取作业批改,直到收到结束信号 while True: student = self.submission_queue.get() if student is None: # None作为结束信号 break teacher.check_test(student) if student.get_result(): with self.lock: self.completed_students += 1 print(f"学生 {student.get_id()} 通过考核") else: # 重做后重新提交队列 threading.Thread(target=self.student_work, args=(student,)).start() self.submission_queue.task_done() def student_work(self, student): # 学生完成作业后提交到队列 student.take_test() self.submission_queue.put(student) def run_test(self): # 启动所有教师线程 teacher_threads = [] for teacher in self.teachers: t = threading.Thread(target=self.teacher_work, args=(teacher,)) teacher_threads.append(t) t.start() # 启动所有学生线程,同时开始做作业 student_threads = [] for student in self.students: t = threading.Thread(target=self.student_work, args=(student,)) student_threads.append(t) t.start() # 等待所有学生完成(包括重做) while True: with self.lock: if self.completed_students == self.total_students: break time.sleep(0.5) # 给每个教师发送结束信号 for _ in self.teachers: self.submission_queue.put(None) # 等待所有教师线程结束 for t in teacher_threads: t.join() print("所有学生完成考核,考试结束") if __name__ == "__main__": studs = Students() studs.create_group(20) teachers = [Teacher("张老师"), Teacher("李老师")] exam = Exam(teachers, studs) exam.run_test()
关键改动说明
- 作业提交队列:用
queue.Queue实现学生作业的排队,学生完成作业后将自己放入队列,教师线程从队列中取任务,自动实现"空闲教师优先处理"的逻辑(Queue的FIFO特性+多线程取任务,空闲的教师会先拿到队列中的学生)。 - 教师独立线程:每个教师启动一个独立线程,持续从队列取学生批改,直到收到
None结束信号,实现教师并行工作。 - 学生重做逻辑:学生未通过时,重新启动一个线程执行做作业+提交队列的流程,直到通过。
- 完成状态统计:用锁保护
completed_students变量,确保多线程下统计准确,当所有学生都通过后,给教师发送结束信号,等待教师线程收尾。 - 去掉全局锁:原代码的全局锁导致教师串行工作,现在改为队列自动调度,教师线程无需全局锁,真正实现并行批改。
内容的提问来源于stack exchange,提问作者cherry_ds
相关产品推荐
相关产品推荐

