1. 使用內置模塊
在使用多線程處理任務時也不是線程越多越好,由于在切換線程的時候,需要切換上下文環(huán)境,依然會造成cpu的大量開銷。為解決這個問題,線程池的概念被提出來了。預先創(chuàng)建好一個合理數量的線程池,讓過來的任務立刻能夠使用,就形成了線程池。
在Python3中,創(chuàng)建線程池是通過concurrent.futures
函數庫中的ThreadPoolExecutor
類來實現的。
import time
import threading
from concurrent.futures import ThreadPoolExecutor
def target():
for i in range(5):
print('running thread-{}:{}'.format(threading.get_ident(), i))
time.sleep(1)
# 創(chuàng)建一個最大容納數量為5的線程池
pool = ThreadPoolExecutor(5)
for i in range(10):
# 往線程池上塞任務
pool.submit(target)
創(chuàng)建線程池還可以使用更優(yōu)雅的方式,就是使用上下文管理器
with ThreadPoolExecutor(5) as pool:
for i in range(100):
pool.submit(target)
直接運行代碼,從輸出可以看出,前面我們設置線程池最大線程數,會保證“同時”僅有五個線程在工作。
running thread-123145483767808:0
running thread-123145489022976:0
running thread-123145494278144:0
running thread-123145499533312:0
running thread-123145504788480:0
running thread-123145483767808:1
running thread-123145489022976:1
running thread-123145499533312:1
running thread-123145494278144:1
running thread-123145504788480:1
running thread-123145489022976:2
running thread-123145499533312:2
running thread-123145483767808:2
running thread-123145504788480:2
running thread-123145494278144:2
....
示例完畢,來說明一下:
使用 with 語句 ,通過 ThreadPoolExecutor 構造實例,同時傳入 max_workers 參數來設置線程池中最多能同時運行的線程數目。
使用 submit 函數來提交線程需要執(zhí)行的任務到線程池中,并返回該任務的句柄(類似于文件、畫圖),注意 submit() 不是阻塞的,而是立即返回。
通過使用 done() 方法判斷該任務是否結束。上面的例子可以看出,提交任務后立即判斷任務狀態(tài),顯示四個任務都未完成。在延時2.5后,task1 和 task2 執(zhí)行完畢,task3 仍在執(zhí)行中。
使用 result() 方法可以獲取任務的返回值。
2. 自定義線程池
除了使用上述第三方模塊的方法之外,我們還可以自己結合前面所學的消息隊列來自定義線程池。
這里我們就使用queue來實現一個上面同樣效果的例子,大家感受一下。
import time
import threading
from queue import Queue
def target(queue):
while True:
task = queue.get()
if task == "stop":
queue.task_done()
break
task()
queue.task_done()
def do_task():
for i in range(5):
print('running thread-{}:{}'.format(threading.get_ident(), i))
time.sleep(1)
class MyQueue(Queue):
def close(self):
for i in range(self.maxsize):
self.put("stop")
def custome_pool(task_func, max_workers):
queue = MyQueue(max_workers)
for n in range(max_workers):
t = threading.Thread(target=task_func, args=(queue,))
t.daemon = True
t.start()
return queue
pool = custome_pool(task_func=target, max_workers=5)
for i in range(10):
pool.put(do_task)
pool.close()
pool.join()
輸出是和上面是完全一樣的效果
running thread-123145469886464:0
running thread-123145475141632:0
running thread-123145485651968:0
running thread-123145490907136:0
running thread-123145480396800:0
running thread-123145469886464:1
running thread-123145480396800:1
running thread-123145475141632:1
running thread-123145490907136:1
running thread-123145485651968:1
...
構建線程池的方法,是可以很靈活的,大家有空可以自己多研究。但是建議只要掌握一種自己熟悉的,能快速上手的就好了。
審核編輯:湯梓紅
-
模塊
+關注
關注
7文章
2738瀏覽量
47805 -
函數
+關注
關注
3文章
4349瀏覽量
63027 -
python
+關注
關注
56文章
4811瀏覽量
85082
發(fā)布評論請先 登錄
相關推薦
買藥秒送 JADE動態(tài)線程池實踐及原理淺析
![買藥秒送 JADE動態(tài)<b class='flag-5'>線程</b><b class='flag-5'>池</b>實踐及原理淺析](https://file1.elecfans.com//web2/M00/06/1B/wKgaombXz-OAS0AAAAnzhAQ2JNQ728.png)
linux驅動程序的編譯方法有哪兩種
利用Python腳本登錄到交換機并創(chuàng)建VLAN
rtt工程移植后線程創(chuàng)建不成功怎么解決?
動態(tài)線程池思想學習及實踐
![動態(tài)<b class='flag-5'>線程</b><b class='flag-5'>池</b>思想學習及實踐](https://file1.elecfans.com//web2/M00/EE/36/wKgaomZqouqAcvrSAAEC2xF7olE477.png)
數字設備中采集數字圖像的兩種方法是什么
使用FreeRTOS創(chuàng)建的DHCP線程里面的DHCP是在哪里定義的?
OpenHarmony語言基礎類庫【@ohos.taskpool(啟動任務池)】
![OpenHarmony語言基礎類庫【@ohos.taskpool(啟動任務<b class='flag-5'>池</b>)】](https://file1.elecfans.com/web2/M00/C5/D1/wKgZomYChGOAUaiiAADe1d8SeRY102.jpg)
java實現多線程的幾種方式
python中5種線程鎖盤點
![<b class='flag-5'>python</b>中5種<b class='flag-5'>線程</b>鎖盤點](https://file1.elecfans.com/web2/M00/C2/F3/wKgZomXpMAiAG5WEAAANt1SVDaM222.jpg)
評論