python 線程池ThreadPoolExecutor(下)(39)

緊接着上一篇文章  python 線程池ThreadPoolExecutor(上) 我們繼續對線程池深入一點了解,其實python中關於線程池,一共有兩個模塊:

1.threadpool — 是一個比較老的模塊了,現在雖然還有一些人在用,但已經不再是主流了;

2.concurrent.futures — 目前線程池主要使用這個模塊,主流模塊;

 

ThreadPoolExecutor常用函數

除了 python 線程池ThreadPoolExecutor(上) 文章中介紹的  submit()  /  cancel()   /  done()  /  result()   函數外,今天還需要額外講解一下另外幾個函數:

 

1.as_completed

雖然 done() 函數提供了判斷任務是否結束的方法,但是並不是太實用,因爲我們並不知道線程到底什麼時候結束,需要一直判斷每個任務有沒有結束。這時就可以使用 as_completed() 方法一次取出所有任務的結果。

as_completed() 方法是一個生成器,在沒有任務完成的時候,會阻塞,在有某個任務完成的時候,就能繼續執行for循環後面的語句,然後繼續阻塞住,循環到所有的任務結束。


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個線程,由於在線程池構造的時候允許同時最多執行2個線程,所以同時執行任務1和任務2,重代碼的輸出結果來看,任務1和任務2執行後,for循環進入阻塞狀態,直到任務1或者任務2結束之後纔會for纔會繼續執行任務3/任務4,並保證同時執行的最多隻有兩個任務(關於自定義時間格式請參考: python time模塊).

 

2.map

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循環輸出的內容依舊是提示先完成的任務3再完成任務2,根據列表urls順序輸出,保證任務的順序性!

 

3.wait

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(下)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章