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))