1.創建線程池ThreadPoolExecutor,提交任務submit(),查詢狀態done(),獲取結果result()
from concurrent.futures import ThreadPoolExecutor
import time
def get_html(times):
time.sleep(times)
print('{}, finished'.format(times))
return times
executor = ThreadPoolExecutor(max_workers=2); #創建線程池,傳入max_workers
參數來設置線程池中最多能同時運行的線程數目
task1 = executor.submit(get_html, 3) # 提交任務
task2 = executor.submit(get_html, 2)
print(task1.done()) # 查詢任務狀態,完成返回True,否則返回False
print(task2.done())
time.sleep(4)
print(task1.done())
print(task2.done())
print(task1.result()) # 獲取任務的返回值,注意:這個方法會阻塞主線程,等待這個任務執行完得到結果
print(task2.result())
if __name__ == '__main__':
pass
2.取消任務cancel()
from concurrent.futures import ThreadPoolExecutor import time def get_html(times): time.sleep(times) print('{}, finished'.format(times)) return times executor = ThreadPoolExecutor(max_workers=1); #創建線程池 task1 = executor.submit(get_html, 3) # 提交任務 task2 = executor.submit(get_html, 2) task1.cancel() task2.cancel() """ 使用cancel()方法可以取消提交的任務,如果任務已經在線程池中運行了,就取消不了 上面的例子,線程池大小為1,添加兩個線程后,第一個線程已經在線程池運行,取消不了,第二個線程還在等待,所以可以取消 """ if __name__ == '__main__': pass
執行結果
3, finished
3.as_completed()
from concurrent.futures import ThreadPoolExecutor, as_completed import time def get_html(times): time.sleep(times) print('{}, finished'.format(times)) return times executor = ThreadPoolExecutor(max_workers=3); #創建線程池 task1 = executor.submit(get_html, 5) # 提交任務 task2 = executor.submit(get_html, 2) for future in as_completed([task1, task2]): print(future.result()) """ as_completed()方法是一個生成器,在沒有任務完成的時候,會阻塞,在有某個任務完成的時候,會yield這個任務,就能執行for循環下面的語句,然后繼續阻塞住,循環到所有的任務結束。 從結果也可以看出,先完成的任務會先通知主線程。 """ if __name__ == '__main__': pass
執行結果:
2, finished 2 5, finished 5
- 循環等待任務執行完過程中如果某個線程拋出異常,則循環停止執行
4. map()
from concurrent.futures import ThreadPoolExecutor, as_completed import time def get_html(times): time.sleep(times) return times executor = ThreadPoolExecutor(max_workers=3); #創建線程池 time_list = [5, 2, 4] for data in executor.map(get_html, time_list): print(data) """ 使用map方法,無需提前使用submit方法,map方法與python標准庫中的map含義相同,都是將序列中的每個元素都執行同一個函數。這里是執行submit函數 上面的代碼就是對time_list的每個元素都執行get_html函數,並分配給線程池。 可以看到執行結果與上面的as_completed方法的結果不同,輸出順序和time_list列表的順序對應,就算2s的任務先執行完成,也會先打印出5s的任務先完成,再打印2s的任務完成。 """ if __name__ == '__main__': pass
執行結果:
5 2 4
5. wait()
from concurrent.futures import ThreadPoolExecutor, as_completed, wait, ALL_COMPLETED import time def get_html(times): time.sleep(times) print("{} task finish".format(times)) return times executor = ThreadPoolExecutor(max_workers=3); #創建線程池 task1 = executor.submit(get_html, 5) task2 = executor.submit(get_html, 2) wait([task1, task2], return_when=ALL_COMPLETED) print("end") """ wait方法接收3個參數,等待的任務序列、超時時間以及等待條件。等待條件return_when默認為ALL_COMPLETED,表明要等待所有的任務都結束。 可以看到運行結果中,確實是所有任務都完成了,主線程才打印出end。 等待條件還可以設置為FIRST_COMPLETED,表示第一個任務完成就停止等待。 """ if __name__ == '__main__': pass
執行結果:
2 task finish 5 task finish end
6.shutdown()
from concurrent.futures import ThreadPoolExecutor, as_completed, wait, ALL_COMPLETED import time def get_html(times): time.sleep(times) print("{} task finish".format(times)) return times executor = ThreadPoolExecutor(max_workers=3); #創建線程池 task1 = executor.submit(get_html, 3) task2 = executor.submit(get_html, 2) for f in as_completed([task1, task2]): print(f.result()) executor.shutdown() """ 在用完一個線程池后,應該調用線程池的shutdown()方法,該方法將啟動線程池的關閉序列。 調用shutdown()方法后的線程池不再接受新任務,但會將以前所有已提交的任務執行完成。當線程池中的所有任務都執行完后,該線程池中的所有線程都會死亡 """ if __name__ == '__main__': pass
執行結果:
2 task finish 2 3 task finish 3