1. 使用內(nèi)置模塊
在使用多線程處理任務時也不是線程越多越好,由于在切換線程的時候,需要切換上下文環(huán)境,依然會造成cpu的大量開銷。為解決這個問題,線程池的概念被提出來了。預先創(chuàng)建好一個合理數(shù)量的線程池,讓過來的任務立刻能夠使用,就形成了線程池。
在Python3中,創(chuàng)建線程池是通過concurrent.futures
函數(shù)庫中的ThreadPoolExecutor
類來實現(xiàn)的。
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)建一個最大容納數(shù)量為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)
直接運行代碼,從輸出可以看出,前面我們設置線程池最大線程數(shù),會保證“同時”僅有五個線程在工作。
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 構(gòu)造實例,同時傳入 max_workers 參數(shù)來設置線程池中最多能同時運行的線程數(shù)目。
使用 submit 函數(shù)來提交線程需要執(zhí)行的任務到線程池中,并返回該任務的句柄(類似于文件、畫圖),注意 submit() 不是阻塞的,而是立即返回。
通過使用 done() 方法判斷該任務是否結(jié)束。上面的例子可以看出,提交任務后立即判斷任務狀態(tài),顯示四個任務都未完成。在延時2.5后,task1 和 task2 執(zhí)行完畢,task3 仍在執(zhí)行中。
使用 result() 方法可以獲取任務的返回值。
2. 自定義線程池
除了使用上述第三方模塊的方法之外,我們還可以自己結(jié)合前面所學的消息隊列來自定義線程池。
這里我們就使用queue來實現(xiàn)一個上面同樣效果的例子,大家感受一下。
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
...
構(gòu)建線程池的方法,是可以很靈活的,大家有空可以自己多研究。但是建議只要掌握一種自己熟悉的,能快速上手的就好了。
審核編輯:湯梓紅
-
模塊
+關(guān)注
關(guān)注
7文章
2783瀏覽量
49552 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4368瀏覽量
64185 -
python
+關(guān)注
關(guān)注
56文章
4825瀏覽量
86171
發(fā)布評論請先 登錄
請問如何在Python中實現(xiàn)多線程與多進程的協(xié)作?
創(chuàng)建了用于OpenVINO?推理的自定義C++和Python代碼,從C++代碼中獲得的結(jié)果與Python代碼不同是為什么?
比較分析兩種不同的可提高柵極驅(qū)動電流的方法

買藥秒送 JADE動態(tài)線程池實踐及原理淺析

linux驅(qū)動程序的編譯方法有哪兩種
邏輯函數(shù)的化簡方法有哪兩種
利用Python腳本登錄到交換機并創(chuàng)建VLAN
rtt工程移植后線程創(chuàng)建不成功怎么解決?
如何在espconn_gethostbyname上創(chuàng)建阻塞線程?
探索虛擬線程:原理與實現(xiàn)

動態(tài)線程池思想學習及實踐

評論