Python的 线程池
线程池的概念是什么?
在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因。
可以理解为我们在多线程执行任务的时候,不需要为每一个任务都创建一个线程来执行(python中不可能无限制的创建多线程),可以将执行完任务的线程重复利用,做到开销小,但执行结果不变的事情。
简单版线程池:
class ThreadingPool: def __init__(self,maxThread = 10): self.maxThread = maxThread self.q = queue.Queue(maxThread) #创建队列 for i in range(maxThread): self.q.put(threading.Thread) #将Thread类名加如队列q中 def getThread(self): return self.q.get() def addThread(self): self.q.put(threading.Thread) #添加新的线程到线程池中 def Foo(num,t): print('num =',num) # t.addThread(threading.Thread) t_p = ThreadingPool() #实例化线程池 for i in range(t_p.maxThread): ret = t_p.getThread() #通过实例获取线程 # print(ret) t = ret(target = Foo,args = (i,t_p)) t.start() #执行线程 t.join() >>> num = 0 num = 1 num = 2 num = 3 num = 4 num = 5 num = 6 num = 7 num = 8 num = 9 num = 0
升级版:
1 import threading,queue,contextlib 2 stop_Obj = object() 3 class ThreadPool: 4 def __init__(self,maxSize): 5 self.maxSize = maxSize 6 # 任务队列 7 self.q = queue.Queue() 8 #终止运行条件 9 self.terminal = False 10 # 已经创建的线程列表 11 self.generate_list =[] 12 # 空闲线程 13 self.free_list = [] 14 15 def call(self): 16 succes = True 17 18 # 获取当前线程 19 20 current_t = threading.current_thread() 21 self.generate_list.append(current_t) 22 23 # 取任务 24 event = self.q.get() 25 while event is not stop_Obj: 26 fun, args,call_fun = event 27 # 执行任务 28 try: 29 ret = fun(*args) 30 except Exception as e: 31 succes = False 32 ret = e 33 # 回调函数 34 if call_fun is not None: 35 try: 36 call_fun(succes,ret) 37 except Exception as e: 38 pass 39 40 # 执行完成后 41 # self.free_list.append(current_t) 42 # 继续获取任务 43 # event = self.q.get() #此处如果任务队列中没有任务的话 会阻塞 44 # self.free_list.remove(current_t) 45 # ↑↑↑ 优化 ↑↑↑ 46 with self.state(current_t): 47 event = self.q.get() 48 49 else: 50 # 如果不是元祖,那就是没有任务了 51 self.generate_list.remove(current_t) 52 53 def generate_thread(self): 54 t = threading.Thread(target = self.call) 55 t.start() 56 57 def run(self,func,args,call_back): 58 if len(self.free_list) <= 0 or len(self.generate_list) < self.maxSize: 59 self.generate_thread() 60 ret = (func, args, call_back) 61 self.q.put(ret) 62 # 任务执行完成后结束线程 63 def close(self): 64 threadNum = len(self.generate_list) 65 while threadNum: 66 self.q.put(stop_Obj) 67 threadNum -=1 68 # 强制终止线程 69 def set_terminal(self): 70 # 终止条件设置 71 self.terminal = True 72 # 清空任务列表 73 self.q.empty() 74 # 添加stopObj来终止此时已经执行完任务但是等待获取任务的线程 75 thread_num = len(self.generate_list) 76 while thread_num: 77 78 self.q.put(stop_Obj) 79 thread_num -= 1 80 81 # 上下文切换 82 @contextlib.contextmanager 83 def state(self,current_t): 84 self.free_list.append(current_t) 85 try: 86 yield 87 finally: 88 self.free_list.remove(current_t) 89 90 91 92 def work_thread(num): 93 print('num = ',num) 94 95 threadPool = ThreadPool(10) 96 for i in range(10): 97 98 threadPool.run(work_thread,(i,),after_fun) 99 100 threadPool.close() >>> num = 0 num = 1 num = 2 num = 3 num = 4 num = 5 num = 6 num = 7 num = 8 num = 9
Process finished with exit code 0
上下文切换管理:
# 自己的 open 文件管理 import contextlib @contextlib.contextmanager def MyOpen(file,mode): f = open(file,mode,encoding= 'utf-8') try: yield f finally: f.close()