import queue import threading import contextlib import time """ 一个基于thread和queue的线程池,以任务为队列元素,动态创建线程,重复利用线程,通过close和terminate方法关闭线程池。 """ # 创建空对象,用于停止线程 StopEvent = object() class ThreadPool(object): def __init__(self, max_num, max_task_num=None): """ max_num ==> 线程池最大线程数 max_task_num ==> 任务队列长度 """ # 如果设置了最大任务参数,则将队列的最大元素个数设置为该值。 if max_task_num: self.q = queue.Queue(max_task_num) else: self.q = queue.Queue() # 设置线程池最多可实例化的线程数 self.max_num = max_num # 任务取消标识 self.cancel = False # 任务中断标识 self.terminal = False # 以实例化的线程列表 self.generate_list = [] # 处于空闲状态的线程列表 self.free_list = [] def run(self, func, args, callback=None): """ 线程池执行一个任务 :param func: 任务函数 :param args: 任务函数所需参数 :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数) :return: 如果线程池已经终止,则返回True否则None """ if self.cancel: return # 将任务函数、参数、回调函数打包放入一个元组中 w = (func, args, callback,) # 将任务放入队列 self.q.put(w) if len(self.free_list) == 0 and len(self.generate_list) < self.max_num: self.generate_thread() # 创建一个线程 def generate_thread(self): """ 创建一个线程 """ t = threading.Thread(target=self.call) # 在线程中执行call函数 t.start() def call(self): """ 循环去获取任务函数并执行任务函数,正常下,每个线程都保存生存状态,直到获取线程终止的flag """ # 获取当前线程的名字 current_thread = threading.currentThread().getName() # 将当前线程的名字加入已实例化的线程列表中 self.generate_list.append(current_thread) # 在任务队列中获取一个任务 event = self.q.get() # 获取的任务不是终止线程的标识对象时 while event != StopEvent: # 解析任务中封装的三个参数 func, args, callable = event # 异常判断 try: ret = func(current_thread, *args) status = True except Exception as e: status = False ret = e if callable != None: try: callable(status, ret) except Exception as e: pass # 当某个线程正常执行完一个任务时,执行work_state方法 with work_state(self.free_list, current_thread): # 如果是强制关闭线程 if self.terminal: # False event = StopEvent # 获取一个正常的任务,并回调work_state方法中的yield语句 else: # 在这里又开始一个正常的任务循环 event = self.q.get() else: # 发现任务是一个终止线程的标识,将线程在已创建线程列表中删除 self.generate_list.remove(current_thread) def close(self): """ 执行完所有任务后,让所有线程都停止 """ # 设置flag self.cancel = True # 计算已创建线程列表中线程的数,然后向任务队列中推送相同数量的终止线程标识 num = len(self.generate_list) while num: self.q.put(StopEvent) num -= 1 def terminate(self): """ 在任务执行过程中终止线程,提前退出 """ self.terminal = True while self.generate_list: self.q.put(StopEvent) self.q.empty() # 该装饰器用于上下文管理 @contextlib.contextmanager def work_state(free_list, thread): # 将当前线程,添加到空闲线程列表中 free_list.append(thread) try: # 等待 yield finally: # 将线程移除空闲列表 free_list.remove(thread) def callable(status, result): """ 根据需要进行回调函数,默认不执行 status ==> 函数的执行状态 result ==> 函数返回值 """ pass def action(thread_name, i): """ 真实任务定义在该函数中 thread_name ==> 执行该方法的线程名 i ==> 该函数需要的参数 """ time.sleep(0.5) print(thread_name, i) # 创建一个最多包含10个线程的线程池 pool = ThreadPool(10) # 创建50个任务 for i in range(50): pool.run(action, (i,), callable) # time.sleep(3) print("33[32;0m任务停止前线程池中有%s个线程,空闲的线程有%s个。33[0m" %(len(pool.generate_list), len(pool.free_list))) # 正常关闭线程池 pool.close() # 强制关闭线程 # pool.terminate()
浙公网安备 33010602011771号