緊接著上一篇文章??python 線程池ThreadPoolExecutor(上)?我們繼續(xù)對線程池深入一點了解,其實python中關(guān)于線程池,一共有兩個模塊:
10年的勐海網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。全網(wǎng)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整勐海建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)公司從事“勐海網(wǎng)站設(shè)計”,“勐海網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。
1.threadpool — 是一個比較老的模塊了,現(xiàn)在雖然還有一些人在用,但已經(jīng)不再是主流了;
2.concurrent.futures — 目前線程池主要使用這個模塊,主流模塊;
?
除了?python 線程池ThreadPoolExecutor(上)?文章中介紹的??submit()? /? cancel()? ?/? done()? /? result()? ?函數(shù)外,今天還需要額外講解一下另外幾個函數(shù):
?
雖然?done()?函數(shù)提供了判斷任務(wù)是否結(jié)束的方法,但是并不是太實用,因為我們并不知道線程到底什么時候結(jié)束,需要一直判斷每個任務(wù)有沒有結(jié)束。這時就可以使用?as_completed()?方法一次取出所有任務(wù)的結(jié)果。
as_completed()?方法是一個生成器,在沒有任務(wù)完成的時候,會阻塞,在有某個任務(wù)完成的時候,就能繼續(xù)執(zhí)行for循環(huán)后面的語句,然后繼續(xù)阻塞住,循環(huán)到所有的任務(wù)結(jié)束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # !usr/bin/env python # -*- coding:utf-8 _*- """ @Author:何以解憂 @Blog(個人博客地址): shuopython.com @WeChat Official Account(微信公眾號):猿說python @Github:www.github.com ? @File:python_ThreadPoolExecutor.py @Time:2019/12/07 21:25 ? @Motto:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累! """ ? ? fromconcurrent.futuresimportThreadPoolExecutor,as_completed importtime ? # 參數(shù)times用來模擬網(wǎng)絡(luò)請求的時間 defdownload_video(index): ????time.sleep(2) ????print("download video {} finished at {}".format(index,time.strftime('%Y-%m-%d %H:%M:%S',time.gmtime()))) ????returnindex ? executor=ThreadPoolExecutor(max_workers=2) urls=[1,2,3,4,5] all_task=[executor.submit(download_video,(url))forurlinurls] ? fortaskinas_completed(all_task): ????data=task.result() ????print("任務(wù){(diào)} down load success".format(data)) |
輸出結(jié)果:
1 2 3 4 5 6 7 8 9 10 | downloadvideo1finishedat2019-12-0702:33:00 任務(wù)1downloadsuccess downloadvideo2finishedat2019-12-0702:33:00 任務(wù)2downloadsuccess downloadvideo3finishedat2019-12-0702:33:02 任務(wù)3downloadsuccess downloadvideo4finishedat2019-12-0702:33:02 任務(wù)4downloadsuccess downloadvideo5finishedat2019-12-0702:33:04 任務(wù)5downloadsuccess |
代碼分析:
5個任務(wù),2個線程,由于在線程池構(gòu)造的時候允許同時最多執(zhí)行2個線程,所以同時執(zhí)行任務(wù)1和任務(wù)2,重代碼的輸出結(jié)果來看,任務(wù)1和任務(wù)2執(zhí)行后,for循環(huán)進入阻塞狀態(tài),直到任務(wù)1或者任務(wù)2結(jié)束之后才會for才會繼續(xù)執(zhí)行任務(wù)3/任務(wù)4,并保證同時執(zhí)行的最多只有兩個任務(wù)(關(guān)于自定義時間格式請參考:?python time模塊).
?
和as_completed()?方法不同的是:map()方法能保證任務(wù)的順序性,舉個例子:如果同時下載5個視頻,就算第二個視頻比第一個視頻先下載完成,也會阻塞等待第一個視頻下載完成并通知主線程之后,第二個下載完成的視頻才回通知主線程,保證按照順序完成任務(wù),下面舉個例子說明一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | fromconcurrent.futuresimportThreadPoolExecutor,as_completed importtime ? # 參數(shù)times用來模擬網(wǎng)絡(luò)請求的時間 defdownload_video(index): ????time.sleep(index) ????print("download video {} finished at {}".format(index,time.strftime('%Y-%m-%d %H:%M:%S',time.gmtime()))) ????returnindex ? executor=ThreadPoolExecutor(max_workers=2) urls=[3,2,1,4,5] ? ? fordatainexecutor.map(download_video,urls): ????print("任務(wù){(diào)} down load success".format(data)) |
輸出結(jié)果:
1 2 3 4 5 6 7 8 9 10 | downloadvideo2finishedat2019-12-0703:38:55 downloadvideo3finishedat2019-12-0703:38:56 任務(wù)3downloadsuccess 任務(wù)2downloadsuccess downloadvideo1finishedat2019-12-0703:38:56 任務(wù)1downloadsuccess downloadvideo4finishedat2019-12-0703:39:00 任務(wù)4downloadsuccess downloadvideo5finishedat2019-12-0703:39:01 任務(wù)5downloadsuccess |
代碼分析:
重上面的輸出結(jié)果看來,即便任務(wù)2比任務(wù)3先完成,for循環(huán)輸出的內(nèi)容依舊是提示先完成的任務(wù)3再完成任務(wù)2,根據(jù)列表urls順序輸出,保證任務(wù)的順序性!
?
wait()方法有點類似線程的join()方法,能阻塞主線程,直到線程池中的所有的線程都操作完成!實例代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | fromconcurrent.futuresimportThreadPoolExecutor,wait,ALL_COMPLETED,FIRST_COMPLETED importtime ? # 參數(shù)times用來模擬網(wǎng)絡(luò)請求的時間 defdownload_video(index): ????time.sleep(2) ????print("download video {} finished at {}".format(index,time.strftime('%Y-%m-%d %H:%M:%S',time.gmtime()))) ????returnindex ? executor=ThreadPoolExecutor(max_workers=2) urls=[1,2,3,4,5] all_task=[executor.submit(download_video,(url))forurlinurls] ? wait(all_task,return_when=ALL_COMPLETED) ? print("main ") |
輸出結(jié)果:
1 2 3 4 5 6 | downloadvideo2finishedat2019-12-0703:50:22 downloadvideo1finishedat2019-12-0703:50:22 downloadvideo3finishedat2019-12-0703:50:24 downloadvideo4finishedat2019-12-0703:50:24 downloadvideo5finishedat2019-12-0703:50:26 main |
wait
方法接收3個參數(shù),等待的任務(wù)序列、超時時間以及等待條件。等待條件return_when
默認為ALL_COMPLETED
,表明要等待所有的任務(wù)都結(jié)束??梢钥吹竭\行結(jié)果中,確實是所有任務(wù)都完成了,主線程才打印出main
。等待條件還可以設(shè)置為FIRST_COMPLETED
,表示第一個任務(wù)完成就停止等待。
?
?
1.python線程隊列Queue-FIFO
2.python 異常處理
3.python __name__ == ‘__main__’詳細解釋
4.python 不定長參數(shù) *argc,**kargcs
?
轉(zhuǎn)載請注明:猿說Python???python 線程池ThreadPoolExecutor(下)