您好,登錄后才能下訂單哦!
這篇文章主要介紹了python線程池怎么應用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇python線程池怎么應用文章都會有所收獲,下面我們一起來看看吧。
傳統多線程方案會使用“即時創建,即時銷毀”的策略。盡管與創建進程相比,創建線程的時間已經大大的縮短,但是如果提交給線程的任務時執行時間較短,而且執行次數及其頻繁,那么服務器將處于不停的創建線程,銷毀線程的狀態。
一個線程的運行時間可以分為三部分:線程的啟動時間、線程體的運行時間和線程的銷毀時間。
在多線程處理的情景中,如果線程不能被重用,就意味著每次線程運行都要經過啟動、銷毀和運行3個過程。這必然會增加系統相應的時間,減低了效率。
線程池在系統啟動時即創建大量空閑的線程,程序只要將一個函數提交給線程池,線程池就會啟動一個空閑的線程來執行它。
當該函數執行結束后,該線程并不會死亡,而是再次返回到線程池中變成空閑狀態,等待執行下一個函數,因此能夠避免多次創建線程,從而節省線程創建和銷毀的開銷,能帶來更好的性能和穩定性。
此外,使用線程池可以有效地控制系統中并發線程的數量。當系統中包含有大量的并發線程時,會導致系統性能急劇下降,甚至導致Python解釋器崩潰,而線程池的最大線程數參數可以控制系統中并發線程的數量不超過此數。
服務器CPU數有限,能夠同時并發的線程數有限,并不是開得越多越好,以及線程切換時有開銷的,如果線程切換過于頻繁,反而會使性能降低。
線程池適用于:突發性大量請求或需要大量線程完成任務,但實際任務處理時間較短的場景
從python3.2開始,標準庫提供了concurrent.futures模塊,它提供了兩個子類:ThreadPoolExecutor和ProcessPoolExecutor。其中ThreadPoolExecutor用于創建線程池,而ProcessPoolExecutor用于創建進程池。不僅可以自動調度線程,還可以做到:
主線程可以獲取某一個線程(或任務)的狀態,以及返回值
當一個線程完成的時候,主線程能夠立即知道
讓多線程和多進程編碼接口一致
使用線程池/進程池來管理并發編程,只要將相應的 task 函數提交給線程池/進程池,剩下的事情就由線程池/進程池來搞定。
ThreadPoolExecutor構造函數有兩個參數:
一個是max_workers參數,用于指定線程池的最大線程數,如果不指定的話則默認是CPU核數的5倍。
另一個參數是thread_name_prefix,它用來指定線程池中線程的名稱前綴(可選),如下:
threadPool = ThreadPoolExecutor(max_workers=self.max_workers, thread_name_prefix="test_")
方法 | 描述 |
submit(fn, *args, **kwargs) | 將 fn 函數提交給線程池。*args 代表傳給 fn 函數的參數,**kwargs 代表以關鍵字參數的形式為 fn 函數傳入參數 |
map(func,*iterables, timeout=None, chunksize=1) | 該函數類似于全局函數 map(func, *iterables),只是該函數將會啟動多個線程,以異步方式立即對 iterables 執行 map 處理 |
shutdown(wait=True) | 關閉線程池。wait=True,等待池內所有任務執行完畢回收完資源后才繼續;wait=False,立即返回,并不會等待池內的任務執行完畢。但不管wait參數為何值,整個程序都會等到所有任務執行完畢 |
程序將 task 函數提交(submit)給線程池后,submit 方法會返回一個 Future 對象,Future 類主要用于獲取線程任務函數的返回值。由于線程任務會在新線程中以異步方式執行,因此線程執行的函數相當于一個“將來完成”的任務,所以 Python 使用 Future 來代表。
方法 | 描述 |
cancel() | 取消該 Future 代表的線程任務。如果該任務正在執行,不可取消,則該方法返回 False;否則,程序會取消該任務,并返回 True |
cancelled() | 返回 Future 代表的線程任務是否被成功取消 |
running() | 如果該 Future 代表的線程任務正在執行、不可被取消,該方法返回 True |
done() | 如果該 Funture 代表的線程任務被成功取消或執行完成,則該方法返回 True |
result(timeout=None) | 獲取該 Future 代表的線程任務最后返回的結果。如果 Future 代表的線程任務還未完成,該方法將會阻塞當前線程,其中 timeout 參數指定最多阻塞多少秒 |
exception(timeout=None) | 獲取該 Future 代表的線程任務所引發的異常。如果該任務成功完成,沒有異常,則該方法返回 None |
add_done_callback(fn) | 為該 Future 代表的線程任務注冊一個“回調函數”,當該任務成功完成時,程序會自動觸發該 fn 函數 |
線程池用完后,應調用線程池的shutdown()方法,關閉線程池。也可使用with語句來管理線程池,可避免手動關閉線程池
示例一(使用submit方式):
from concurrent.futures import ThreadPoolExecutor # 導入ThreadPoolExecutor模塊 import time max_workers = 5 t = [] t1 = time.time() # 作為線程任務的函數 def task(x, y): return x + y threadPool = ThreadPoolExecutor(max_workers) # 創建最大線程數為max_workers的線程池 for i in range(20): # 循環向線程池中提交task任務 future = threadPool.submit(task, i, i+1) t.append(future) # 若不需要獲取返回值,則可不需要下面兩行代碼 for i in t: print(i.result()) # 獲取每個任務的返回值,result()會阻塞主線程 threadPool.shutdown() # 阻塞主線程,所有任務執行完后關閉線程池 print(time.time() - t1)
示例二(使用map方式):
from concurrent.futures import ThreadPoolExecutor # 導入ThreadPoolExecutor模塊 max_workers = 5 t = [] t1 = time.time() # 作為線程任務的函數 def task(x): return x + (x + 1) args = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) with ThreadPoolExecutor(max_workers) as threadPool: # 創建最大線程數為max_workers的線程池 results = threadPool.map(task, args) # 啟動線程,并收集每個線任務的返回結果 # 若無返回值,則可不需要下面兩行代碼 for i in results: print(i)
示例三:
as_complete():是一個生成器,在沒有任務完成的時候會阻塞,在有某個任務完成的時候會yield這個任務,執行語句,繼續阻塞,循環到所有任務結束,先完成的任務會先通知主線程
from concurrent.futures import ThreadPoolExecutor, as_completed import time max_workers = 5 t = [] t1 = time.time() # 作為線程任務的函數 def task(x, y): return x + y def handle_result(future): print(future.result()) with ThreadPoolExecutor(max_workers) as threadPool: # 創建最大線程數為max_workers的線程池 for i in range(20): # 循環向線程池中提交task任務 future = threadPool.submit(task, i, i+1) t.append(future) # 若不需要獲取返回值,則可不需要下面兩行代碼 for future in as_completed(t): # as_completed,哪個先完成就先處理哪個,會阻塞主線程,直到完成所有,除非設置timeout future.add_done_callback(handle_result)
關于“python線程池怎么應用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“python線程池怎么應用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。