1. 使用內(nèi)置模塊
在使用多線程處理任務(wù)時(shí)也不是線程越多越好,由于在切換線程的時(shí)候,需要切換上下文環(huán)境,依然會(huì)造成cpu的大量開銷。為解決這個(gè)問題,線程池的概念被提出來了。預(yù)先創(chuàng)建好一個(gè)合理數(shù)量的線程池,讓過來的任務(wù)立刻能夠使用,就形成了線程池。
在Python3中,創(chuàng)建線程池是通過concurrent.futures
函數(shù)庫中的ThreadPoolExecutor
類來實(shí)現(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)建一個(gè)最大容納數(shù)量為5的線程池
pool = ThreadPoolExecutor(5)
for i in range(10):
# 往線程池上塞任務(wù)
pool.submit(target)
創(chuàng)建線程池還可以使用更優(yōu)雅的方式,就是使用上下文管理器
with ThreadPoolExecutor(5) as pool:
for i in range(100):
pool.submit(target)
直接運(yùn)行代碼,從輸出可以看出,前面我們設(shè)置線程池最大線程數(shù),會(huì)保證“同時(shí)”僅有五個(gè)線程在工作。
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)造實(shí)例,同時(shí)傳入 max_workers 參數(shù)來設(shè)置線程池中最多能同時(shí)運(yùn)行的線程數(shù)目。
使用 submit 函數(shù)來提交線程需要執(zhí)行的任務(wù)到線程池中,并返回該任務(wù)的句柄(類似于文件、畫圖),注意 submit() 不是阻塞的,而是立即返回。
通過使用 done() 方法判斷該任務(wù)是否結(jié)束。上面的例子可以看出,提交任務(wù)后立即判斷任務(wù)狀態(tài),顯示四個(gè)任務(wù)都未完成。在延時(shí)2.5后,task1 和 task2 執(zhí)行完畢,task3 仍在執(zhí)行中。
使用 result() 方法可以獲取任務(wù)的返回值。
2. 自定義線程池
除了使用上述第三方模塊的方法之外,我們還可以自己結(jié)合前面所學(xué)的消息隊(duì)列來自定義線程池。
這里我們就使用queue來實(shí)現(xiàn)一個(gè)上面同樣效果的例子,大家感受一下。
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文章
2788瀏覽量
50454 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4381瀏覽量
64945 -
python
+關(guān)注
關(guān)注
56文章
4827瀏覽量
86825
發(fā)布評(píng)論請先 登錄
RT-Thread Nano移植后動(dòng)態(tài)創(chuàng)建線程創(chuàng)建不了怎么處理?
六相永磁同步電機(jī)串聯(lián)系統(tǒng)控制的兩種方法分析研究
請問如何在Python中實(shí)現(xiàn)多線程與多進(jìn)程的協(xié)作?
創(chuàng)建了用于OpenVINO?推理的自定義C++和Python代碼,從C++代碼中獲得的結(jié)果與Python代碼不同是為什么?
芯片制造過程中的兩種刻蝕方法

socket 多線程編程實(shí)現(xiàn)方法
Python中多線程和多進(jìn)程的區(qū)別

比較分析兩種不同的可提高柵極驅(qū)動(dòng)電流的方法

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

評(píng)論