ThreadPoolExecutor线程池的理解与应用
生活随笔
收集整理的這篇文章主要介紹了
ThreadPoolExecutor线程池的理解与应用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、線程池與進程池的區別
兩個關鍵詞:線程,進程/池
池:可以將其理解為一種容器,有其固定的大小
什么時候用線程池/進程池,分兩個問題討論
1.什么時候用池:當程序中的任務并發數遠遠大于計算機的承受能力時,就應該用池的概念將開啟的進程數或者線程數限制在計算機的承受范圍之內
2.用什么樣的池:用進程池還是線程池取決于程序的類型,對于IO密集型—>線程,對于計算密集型—>進程
這就涉及到并發和并行概念的區別。并發,是指一個處理器(進程)能同時處理多個任務;并行,指的是多個處理器(進程)同時處理多個不同的任務。一般可以認為多線程用于并發任務處理,而多進程用于并行任務處理。因此,當任務是IO型的,適合用線程池的方式,因為一個線程被IO掛起,其他的線程可以繼續執行;而如果任務是CPU型的,適合用進程池的方式,此時并未掛起,需要同時執行任務。
二、實用案例
下載網頁的代碼為例,由于是IO密集型的,可以使用線程池
代碼:
結果如下:
get page 0 start get page 1 start get page 2 start get page 0 finished get page 3 start (0, 5) get page 1 finished get page 4 start (1, 5) get page 3 finished get page 4 finished get page 2 finished (2, 50) (3, 5) (4, 5) thread pool exe time:50.0結論:
1、有加速的作用
存在的問題:
task.result一定要等待前面任務的結果返回,才能獲取后面任務的結果,這里可以用as_complete優化
加入as_complete如下:
from concurrent.futures import ThreadPoolExecutor, as_completed import time# 參數times用來模擬網絡請求的時間 def get_html(i, times=5):print("get page {} start".format(i))if i == 2:times *= 10time.sleep(times) # 模擬IO行為print("get page {} finished".format(i))return i, timest0 = time.time() for i in range(5):get_html(i) t00 = time.time() print(f'normal exe time:{t00 - t0}')executor = ThreadPoolExecutor(max_workers=3) # 通過submit函數提交執行的函數到線程池中,submit函數立即返回,不阻塞tasks = [executor.submit(get_html, i) for i in range(5)] # result方法可以獲取task的執行結果 t1 = time.time() for task in as_completed(tasks):print(task.result()) t2 = time.time() print(f'thread pool exe time:{t2 - t1}') get page 0 start get page 0 finished get page 1 start get page 1 finished get page 2 start get page 2 finished get page 3 start get page 3 finished get page 4 start get page 4 finished normal exe time:70.0 get page 0 start get page 1 start get page 2 start get page 0 finished get page 3 start (0, 5) get page 1 finished get page 4 start (1, 5) get page 3 finished (3, 5) get page 4 finished (4, 5) get page 2 finished (2, 50) thread pool exe time:50.0結論:as_completed()方法是一個生成器,在沒有任務完成的時候,會阻塞,在有某個任務完成的時候,會yield這個任務,就能執行for循環下面的語句,然后繼續阻塞住,循環到所有的任務結束。從結果也可以看出,先完成的任務會先通知主線程
總結
以上是生活随笔為你收集整理的ThreadPoolExecutor线程池的理解与应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用python正确的获取文件最后被修改的
- 下一篇: _Linux系统编程—信号集操作函数