python

您所在的位置:网站首页 自定义线程池的使用实验报告 python

python

2024-04-14 21:46| 来源: 网络整理| 查看: 265

一:自定义线程池的实现 前戏: 在进行自定义线程池前,先了解下Queue队列

队列中可以存放基础数据类型,也可以存放类,对象等特殊数据类型

from queue import Queue class T: def __init__(self,num): self.num = num def printf(self): print(self.num,id(self.num)) if __name__ == "__main__": queue = Queue(0) num = 12 queue.put(num) #可以存放基础数据类型 t = T(num) queue.put(t) #可以存放对象 cls = T queue.put(cls) #可以存放类 dt = queue.get() print(id(dt),dt,type(dt)) #1385649280 12 dt = queue.get() print(id(dt),dt,type(dt)) #7652128 dt = queue.get() print(id(dt),dt,type(dt)) #18042264

 

线程池应该具备的功能: 先创建线程池, 之后去获取数据的时候,若是有直接拿走 若是没有,需要去阻塞等待,直到有数据到达 线程池可以设置指定大小 满足上面“阻塞”要求,设置大小,的数据结构,我们可以使用Queue队列 简单版本(Low,简单了解,不要使用): import threading from queue import Queue class ThreadPool(object): def __init__(self,max_num): self.queue = Queue(max_num) for i in range(max_num): self.queue.put(threading.Thread) #存放了max_num个类名,是指向同一个内存空间的 def get_thread(self): return self.queue.get() #获取一个类名 def add_thread(self): self.queue.put(threading.Thread) def func(pool,i): print(i) pool.add_thread() #在我们从队列中获取一个线程类时,我们需要去放入一个,始终保持10个 if __name__ == "__main__": p = ThreadPool(10) #生成10个线程在线程池 for i in range(100): thread = p.get_thread() #获取一个线程(实际上只是获取类名) t = thread(target=func,args=(p,i,)) t.start() 上面这个Low版线程池,只是使用队列来维护一个数量,能够保持阻塞这一功能。队列中只包含了线程类名(所有类名指向一个内存空间),当我们获取到类名产生的线程,无法复用,浪费空间,而且,操作复杂,不太明了 改进版: 需求:想要实现线程复用,首先考虑,每个线程只可以绑定一个执行函数,那么如何去执行多个任务: 1.可以在执行函数中去调用任务,再去执行。 2.将任务放在队列中,那么线程可以在执行函数中循环从队列中获取任务,再去执行。没有任务,那么线程将阻塞,等待任务到来,继续去执行。

实现:1.创建队列去存放任务(无限个任务都可以)

2.设置一个统一的执行函数,所有的线程都会从这个执行函数中去获取到任务,回调执行。

 

需求:同进程池相比。 1.创建线程池时,不是马上去创建所有的线程,而是当有需求的时候再去创建线程,线程数量不能超过我们所要求的。 2.当任务较多,复杂,此时可能就需要去将所有的线程都生成, 3.当任务简单,那我们完全不必要去生成所有的线程,这样浪费空间。我们只需要去使用开始创建的那几个线程去执行这些任务即可。

实现:1.我们需要一个变量去标识我们最大应该创建的线程数(没有则是可以一直创建)

2.我们需要一个变量去标志我们创建了多少线程(一个线程列表,去存放我们真实创建的线程数generate_list)

3.我们需要一个变量去标识我们空闲的线程数(一个线程列表,去存放我们的空闲线程free_list)

 

需求:1.如何终止所有线程: 实现: 1.close方法:(当所有任务结束后)设置标识,当从任务队列中获取到该标识(StopEvent),当前线程就移出已生成线程列表,并销毁。所以我们可以向队列中加入对应线程数的停止符

2.terminate方法:设置标识,Flag,当其为False时,终止线程(不管是否还有任务,当执行完现在的任务后将其他的任务舍弃,然后跳出任务循环),为了防止当执行terminate方法(设置了Flag后),在获取任务处处阻塞,在terminate方法设置完标识后加入终止符StopEvent

实现代码: import threading import time from queue import Queue StopEvent = object() #这是一个标志(可以写成其他的数据,像是NULL或者其他),标志任务停止,向队列中加入相应个数的对象,每个线程,谁获取,谁终止 class ThreadPool(object): def __init__(self,max_num): self.max_num = max_num #最多创建的线程数量(线程池最大容量) self.generate_list = [] #(真实已经创建的线程列表) self.free_list = [] #空闲的线程列表 self.queue = Queue() #用于存放任务(函数名,参数,回调)的队列,不对其限制大小 self.terminal = False #是否直接终止 def run(self,func,args=(),callback=None): ''' 加任务到队列中 :param func: :param args: :param callback: :return: ''' evt = (func,args,callback) self.queue.put(evt) #将任务放入到队列中 #若是空闲列表为空,且还允许再去生成线程,则去生成一个新的线程,否则等待 if len(self.free_list) == 0 and len(self.generate_list)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3