您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關什么是Python中的線程池,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
線程池
傳統多線程問題?
傳統多線程方案會使用“即時創建, 即時銷毀”的策略。盡管與創建進程相比,創建線程的時間已經大大的縮短,但是如果提交給線程的任務是執行時間較短,而且執行次數極其頻繁,那么服務器將處于不停的創建線程,銷毀線程的狀態。
一個線程的運行時間可以分為3部分:線程的啟動時間、線程體的運行時間和線程的銷毀時間。在多線程處理的情景中,如果線程不能被重用,就意味著每次創建都需要經過啟動、銷毀和運行3個過程。這必然會增加系統相應的時間,降低了效率。
有沒有一種高效的解決方案呢? —— 線程池
線程池基本原理:
我們把任務放進隊列中去,然后開N個線程,每個線程都去隊列中取一個任務,執行完了之后告訴系統說我執行完了,然后接著去隊列中取下一個任務,直至隊列中所有任務取空,退出線程。
使用線程池:
由于線程預先被創建并放入線程池中,同時處理完當前任務之后并不銷毀而是被安排處理下一個任務,因此能夠避免多次創建線程,從而節省線程創建和銷毀的開銷,能帶來更好的性能和系統穩定性。
線程池要設置為多少?
服務器CPU核數有限,能夠同時并發的線程數有限,并不是開得越多越好,以及線程切換是有開銷的,如果線程切換過于頻繁,反而會使性能降低。
線程執行過程中,計算時間分為兩部分:
1.CPU計算,占用CPU。
2.不需要CPU計算,不占用CPU,等待IO返回,比如recv(), accept(), sleep()等操作,具體操作就是比如:訪問cache、RPC調用下游service、訪問DB,等需要網絡調用的操作。
那么如果計算時間占50%, 等待時間50%,那么為了利用率達到最高,可以開2個線程:
假如工作時間是2秒, CPU計算完1秒后,線程等待IO的時候需要1秒,此時CPU空閑了,這時就可以切換到另外一個線程,讓CPU工作1秒后,線程等待IO需要1秒,此時CPU又可以切回去,第一個線程這時剛好完成了1秒的IO等待,可以讓CPU繼續工作,就這樣循環的在兩個線程之前切換操作。
那么如果計算時間占20%, 等待時間80%,那么為了利用率達到最高,可以開5個線程:
可以想象成完成任務需要5秒,CPU占用1秒,等待時間4秒,CPU在線程等待時,可以同時再激活4個線程,這樣就把CPU和IO等待時間,最大化的重疊起來。
抽象一下,計算線程數設置的公式就是:
N核服務器,通過執行業務的單線程分析出本地計算時間為x,等待時間為y,則工作線程數(線程池線程數)設置為 N*(x+y)/x,能讓CPU的利用率最大化。
由于有GIL的影響,python只能使用到1個核,所以這里設置N=1。
import queue import threading import 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) # 任務異步出隊,Queue內部實現了同步機制 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() work_manager = WorkManager(100, 10) # 或者work_manager = WorkManager(10000, 20) work_manager.wait_allcomplete() end = time.time() print("cost all time: %s" % (end - start))
上述就是小編為大家分享的什么是Python中的線程池了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。