黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

python線程池

系統 1924 0

1. 何時使用線程池

系統啟動一個新線程的成本是比較高的,因為它涉及與操作系統的交互。在這種情形下,使用線程池可以很好地提升性能;
尤其是當程序中需要創建大量生存期很短暫的線程時,更應該考慮使用線程池。

線程池在系統啟動時即創建大量空閑的線程,程序只要將一個函數提交給線程池,線程池就會啟動一個空閑的線程來執行它。
當該函數執行結束后,該線程并不會死亡,而是再次返回到線程池中變成空閑狀態,等待執行下一個函數。

使用線程池可以有效地控制系統中并發線程的數量。當系統中包含有大量的并發線程時,會導致系統性能急劇下降,甚至導致 Python 解釋器崩潰,而線程池的最大線程數參數可以控制系統中并發線程的數量不超過此數。

2. 線程池

線程池的基類是concurrent.futures模塊中的Executor, Executor提供了兩個子類,即ThreadPoolExecutor 和 ProcessPoolExecutor

ThreadPoolExecutor?? ??? ?線程池
ProcessPoolExecutor?? ??? ?進程池

使用線程池/進程池來管理并發編程,那么只要將相應的task函數提交給線程池/進程池,剩下的就由線程池/進程池來做

常用方法:
submit(fn, *args, **kwargs)
fn 函數?
*args ? ? ?傳給fn函數的參數
*kargs ? ? 以關鍵字參數的形式傳給fn函數的參數

map(func, *iterables, timeout = None, chunksize = 1)
類似全局函數map(func, *iterables),只是該函數將會啟動多個線程,以異步方式立即對iterables執行map處理

shutdown(wait=True)

程序將task函數提交給線程池后,submit方法會返回一個Future對象,Future類主要用于獲取線程任務函數的返回值。
由于線程任務會在新線程中以異步方式執行,因此,線程執行的函數相當于一個“將來完成”的任務,所以使用Future來代表

Future提供了以下方法:
cancel():?? ??? ??? ?取消該Future代表的線程任務。如果該任務正在執行,不可取消,則該方法返回False;否則,程序會取消該任務,并返回True。
cancelled(): ?? ?返回Future代表的線程任務是否被成功取消
running():?? ??? ?如果該Future代表的線程任務正在執行、不可被取消,該方法返回True。
done():?? ??? ??? ??? ?如果該Future代表的線程任務被成功取消或這行完成,則該方法返回True。
result(timeout=None):?? ?獲取該Future代表的線程任務最后返回的結果。如果Future代表的線程任務還未能完成,該方法將會阻塞當前線程,其中timeout參數指定最多阻塞多少秒
exception(timeout=None): ?? ?獲取該Future代表的線程任務所引發的異常,如果該任務成功完成,沒有異常,則該方法返回None
add_done_callback(fn):?? ??? ?為該Future代表的線程任務注冊一個“回調函數”,當該任務成功完成時,程序會自動觸發該fn函數

在用完一個線程池后,應該調用該線程池的shutdown()方法,該方法將啟動線程池的關閉序列。
調用shutdown()方法后的線程池不再接受新任務,但會將以前所有的已提交的任務執行完成。當線程池中的所有任務都執行完成后,該線程池中的所有線程都會死亡。


示例:

"""
使用線程池來執行線程任務:
1. 調用ThreadPoolExecutor類的構造器創建一個線程池
2. 定義一個普通函數作為線程任務
3. 調用ThreadPoolExecutor對象的submit()方法來提交線程任務
4. 當不想提交任何任務時,調用ThreadPoolExecutor對象的shutdown()方法來關閉線程池
"""

from concurrent.futures import ThreadPoolExecutor
import threading
import time

#線程任務
def task(max):
? ? my_sum = 0
? ? for i in range(max):
? ? ? ? print(threading.current_thread().name + ' ' + str(i))
? ? ? ? my_sum += i
? ? return my_sum

#創建一個包含2條線程的線程池
pool = ThreadPoolExecutor(max_workers = 2)

#向線程池提交一個task,
future1 = pool.submit(task, 50)

#向線程池再提交一個task
future2 = pool.submit(task, 100)

#判斷future1代表的任務是否結束
print(future1.done())

time.sleep(3)

#判斷future2代表的任務是否結束
print(future2.done())


#查看future1代表的任務返回結果
print(future1.result()) ? ? ? ? ? ? #會阻塞主線程在此等待
#查看future2代表的任務返回結果
print(future2.result())


#如果想不阻塞主線程,可以使用add_done_callback方法
#示例:
#def callback_get_result(future):
# ? future.result()
#
#future1.add_done_callback(callback_get_result)
#future2.add_done_callback(callback_get_result)


#關閉線程池
pool.shutdown()

由于線程池實現了上下文管理協議(Context Manage Protocol),因此,程序可以使用with語句來管理線程池,這樣即可避免手動關閉線程池

Executor提供了一個map(func, *iterables, timeout=None, chunksize=1)方法
類似于全局函數map()
區別在于線程池的map()會為iterables的每個元素啟動一個線程,已并發方式執行func函數。這種方式相當于啟動len(iterables)個線程,并收集每個線程的執行結果。


示例:

with ThreadPoolExecutor(max_workers=4) as pool:
?? ?#使用map,元組中有3個元素,因此程序啟動3條線程來執行task
?? ?results = pool.map(task, (50,100,250))?? ?
?? ?


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論