基于队列queue实现的线程池
本文通过文章同步功能推送至博客园,显示排版可能会有所错误,请见谅!
写在前文:在Python中给多进程提供了进程池类,对于线程,Python2并没有直接提供线程池类(Python3中提供了线程池功能),而线程池在并行中应用较广泛,因此实现一个进程池的功能十分必要。本文基于队列(queue)功能来实现线程池功能。
在Python3标准库中提供了线程池、进程池功能,推荐使用标准库。
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ProcessPoolExecutor
实现代码:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- __auth__ = "SongWei" import threading,queue,time class Threadpool: '''基于队列queue实现的线程池''' def __init__(self,max_thread=1): '''创建进程队列''' self.queue = queue.Queue(maxsize=max_thread) def apply(self,target=None,args=(),callback=None,calljoin=True,**kwargs): ''':param callback 回调函数 当子线程函数运行结束后将返回值传入回调函数 :param calljoin 布尔值 回调函数是否阻塞进程池 默认True 只有当目标函数和回调函数都执行结束后才视为该线程结束 其他参数同threading.Thread类 注意:只有当目标函数和回调函数都执行结束后,消息队列才会取回值(即回调函数会阻塞线程池) ''' if not callback: callback = self._callback t = threading.Thread(target=self._decorate(target,callback,calljoin),args=args,**kwargs) self.queue.put(t) t.start() def join(self): ''' 当线程池中还有未执行结束的子线程时 阻塞主线程 注意:当calljoin=False时 因回调函数在消息队列取回后才执行 故join不会等待回调函数 ''' while self.queue.qsize(): time.sleep(0.05) def _decorate(self,target,callback,calljoin): ''':param target 接收一个目标函数 :param callback 接受一个回调函数 :param backjoin 布尔值 若为真 则当回调函数执行结束后才释放队列 否则 当目标函数执行结束后就会释放队列 本函数本质上是一个装饰器,即运行目标函数后,执行队列取回(self.queque.get()),并将返回值作为参数执行回调函数。 ''' def wrapper(*args,**kwargs): res = target(*args,**kwargs) if calljoin: callback(res) self.queue.get() else: self.queue.get() callback(res) return res return wrapper def _callback(self,*args,**kwargs): '''没有传入回调函数时 什么也不干''' pass 调用示例: result_list = [] def func(arg): print('正在等待执行%s' % arg) time.sleep(10) return arg def back(res): print('我已经取回了数据:%s' % res) result_list.append(res) pool = Threadpool(max_thread=20) for i in range(40): pool.apply(target=func,args=(i,),callback=back) pool.join() print(result_list)