python线程池问题
线程池基本原理
把任务放进队列中去,然后开N个线程,每个线程都去队列中取一个任务,执行完了之后告诉系统说我执行完了,然后接着去队列中取下一个任务,直至队列中所有任务取空,退出线程
线程池优点
由于线程预先被创建并放入线程池中,同时处理完当前任务之后并不销毁而是被安排处理下一个任务,因此能够避免多次创建线程,从而节省线程创建和销毁的开销,能带来更好的性能和系统稳定性
设置线程池的线程数---限制
- 服务器CPU核数有限,能够同时并发的线程数有限
- 线程切换是有开销的,如果线程切换过于频繁,会使性能降低
计算原理:
- 即计算时间占50%,等待时间50%,那么为了利用率达到最高,可以开2个线程
- 如果计算时间占20%, 等待时间80%,那么为了利用率达到最高,可以开5个线程
计算线程数设置的公式----
N核服务器,通过执行业务的单线程分析出本地计算时间为x,等待时间为y,则工作线程数(线程池线程数)设置为 N*(x+y)/x,能让CPU的利用率最大化。
Tips:由于有GIL的影响,python只能使用到1个核,所以这里设置N=1
import queue,threading,time class WorkManager(object): def __init__(self,work_num=1000,thread_num=2): self.work_queue=queue.Queue self.threads=[] self.__init_work_queue(work_num) self.__init_thread_pool(thread_num) #初始化线程 def __init_thread_pool(self,thread_num): for i in range(thread_num): self.threads.append(Work(self.work_queue)) #初始化工作队列 def __init_work_queue(self,jobs_num): for i in range(jobs_num): self.add_job(do_job,i) #添加一项工作入队 def add_job(self,func,*args): self.work_queue.put((func,list(args))) #任务入队,Queue内部已经实现了同步机制 #等待所有线程运行完毕 def wait_allcomplete(self): for item in self.threads: if item.isAlive(): item.join() class Work(threading.Thread): def __init__(self,work_queue): threading.Thread.__init__(self) self.work_queue=work_queue self.start() def run(self): #死循环,从而让创建的线程在一定条件下关闭退出 while True: try: do,args=self.work_queue.get(block=False)###任务异步出队列 do(args) self.work_queue.task_done() #通知系统任务完成 except: break #具体要做的任务 def do_job(args): time.sleep(0.1) print(threading.current_thread()) print(list(args)) if __name__='__main__': start=time.time() workManage=WorkManager(100,10) #workManage=WorkManager(10000,20) workManage.wait_allcomplete() end=time.time() print("cost all time: %s"%(end-start))