您好,登錄后才能下訂單哦!
緊接著上一篇文章??python 線程池ThreadPoolExecutor(上)?我們繼續(xù)對線程池深入一點了解,其實python中關于線程池,一共有兩個模塊:
1.threadpool — 是一個比較老的模塊了,現在雖然還有一些人在用,但已經不再是主流了;
2.concurrent.futures — 目前線程池主要使用這個模塊,主流模塊;
?
除了?python 線程池ThreadPoolExecutor(上)?文章中介紹的??submit()? /? cancel()? ?/? done()? /? result()? ?函數外,今天還需要額外講解一下另外幾個函數:
?
雖然?done()?函數提供了判斷任務是否結束的方法,但是并不是太實用,因為我們并不知道線程到底什么時候結束,需要一直判斷每個任務有沒有結束。這時就可以使用?as_completed()?方法一次取出所有任務的結果。
as_completed()?方法是一個生成器,在沒有任務完成的時候,會阻塞,在有某個任務完成的時候,就能繼續(xù)執(zhí)行for循環(huán)后面的語句,然后繼續(xù)阻塞住,循環(huán)到所有的任務結束。
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:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累! """ ? ? from concurrent.futures import ThreadPoolExecutor, as_completed import time ? # 參數times用來模擬網絡請求的時間 def download_video(index): ????time.sleep(2) ????print("download video {} finished at {}".format(index,time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()))) ????return index ? executor = ThreadPoolExecutor(max_workers=2) urls = [1, 2, 3, 4, 5] all_task = [executor.submit(download_video, (url)) for url in urls] ? for task in as_completed(all_task): ????data = task.result() ????print("任務{} down load success".format(data)) |
輸出結果:
1 2 3 4 5 6 7 8 9 10 | download video 1 finished at 2019-12-07 02:33:00 任務1 down load success download video 2 finished at 2019-12-07 02:33:00 任務2 down load success download video 3 finished at 2019-12-07 02:33:02 任務3 down load success download video 4 finished at 2019-12-07 02:33:02 任務4 down load success download video 5 finished at 2019-12-07 02:33:04 任務5 down load success |
代碼分析:
5個任務,2個線程,由于在線程池構造的時候允許同時最多執(zhí)行2個線程,所以同時執(zhí)行任務1和任務2,重代碼的輸出結果來看,任務1和任務2執(zhí)行后,for循環(huán)進入阻塞狀態(tài),直到任務1或者任務2結束之后才會for才會繼續(xù)執(zhí)行任務3/任務4,并保證同時執(zhí)行的最多只有兩個任務(關于自定義時間格式請參考:?python time模塊).
?
和as_completed()?方法不同的是:map()方法能保證任務的順序性,舉個例子:如果同時下載5個視頻,就算第二個視頻比第一個視頻先下載完成,也會阻塞等待第一個視頻下載完成并通知主線程之后,第二個下載完成的視頻才回通知主線程,保證按照順序完成任務,下面舉個例子說明一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from concurrent.futures import ThreadPoolExecutor, as_completed import time ? # 參數times用來模擬網絡請求的時間 def download_video(index): ????time.sleep(index) ????print("download video {} finished at {}".format(index,time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()))) ????return index ? executor = ThreadPoolExecutor(max_workers=2) urls = [3, 2, 1, 4, 5] ? ? for data in executor.map(download_video,urls): ????print("任務{} down load success".format(data)) |
輸出結果:
1 2 3 4 5 6 7 8 9 10 | download video 2 finished at 2019-12-07 03:38:55 download video 3 finished at 2019-12-07 03:38:56 任務3 down load success 任務2 down load success download video 1 finished at 2019-12-07 03:38:56 任務1 down load success download video 4 finished at 2019-12-07 03:39:00 任務4 down load success download video 5 finished at 2019-12-07 03:39:01 任務5 down load success |
代碼分析:
重上面的輸出結果看來,即便任務2比任務3先完成,for循環(huán)輸出的內容依舊是提示先完成的任務3再完成任務2,根據列表urls順序輸出,保證任務的順序性!
?
wait()方法有點類似線程的join()方法,能阻塞主線程,直到線程池中的所有的線程都操作完成!實例代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED, FIRST_COMPLETED import time ? # 參數times用來模擬網絡請求的時間 def download_video(index): ????time.sleep(2) ????print("download video {} finished at {}".format(index,time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()))) ????return index ? executor = ThreadPoolExecutor(max_workers=2) urls = [1, 2, 3, 4, 5] all_task = [executor.submit(download_video,(url)) for url in urls] ? wait(all_task,return_when=ALL_COMPLETED) ? print("main ") |
輸出結果:
1 2 3 4 5 6 | download video 2 finished at 2019-12-07 03:50:22 download video 1 finished at 2019-12-07 03:50:22 download video 3 finished at 2019-12-07 03:50:24 download video 4 finished at 2019-12-07 03:50:24 download video 5 finished at 2019-12-07 03:50:26 main |
wait
方法接收3個參數,等待的任務序列、超時時間以及等待條件。等待條件return_when
默認為ALL_COMPLETED
,表明要等待所有的任務都結束。可以看到運行結果中,確實是所有任務都完成了,主線程才打印出main
。等待條件還可以設置為FIRST_COMPLETED
,表示第一個任務完成就停止等待。
?
?
1.python線程隊列Queue-FIFO
2.python 異常處理
3.python __name__ == ‘__main__’詳細解釋
4.python 不定長參數 *argc,**kargcs
?
轉載請注明:猿說Python???python 線程池ThreadPoolExecutor(下)
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。