GIL的理解
GIL這個話題至今也是個爭議較多的,對於不用應用場景對線程的需求也就不一樣,說下我聽過的優勢:
1. 我沒有用過其餘語言的多線程,因此沒法比較什麼,可是對於I/O而言,Python的線程仍是比較高效的。
2. 有些第三方基於Python的框架和庫,好比Tensorflow等基於C/C plus plus重寫的Python線程機制。
3. 至於換成Cython編譯器解決GIL,這個只是聽過,沒用過。
4. Python多線程對於web、爬蟲方面也能夠表現出較好的性能。
5. Python多進程是無缺的,能夠把資源消耗較少的非必要線程工做轉爲多進程來工做。
6. 計算密集型就別想多線程了,一概多進程。
7. Python還有細粒度且高效的協程。
8. 若是有N核CPU,那麼同時並行的進程數就是N,每一個進程裏面只有一個線程能搶到工做權限。
因此同一時刻最大的並行線程數=進程數=CPU的核數(這條個人我的理解很模糊,參考吧)
多線程
多線程有2種經過start的那種方式,很是廣泛,此處就不寫了。
新版線程池 future庫 是python3.2新出的功能(記住這個future)
方式1:(sublime運行後直接貼上來了)
from time import sleep
from concurrent.futures import ThreadPoolExecutor,as_completed,ALL_COMPLETED,wait
executor = ThreadPoolExecutor(max_workers=10) # 初始化線程池10個坑
def f():
sleep(15)
return 100
all_tasks = [executor.submit(f) for _ in range(10)] # 提交10個線程,全放池裏執行
# for per_thread in as_completed(all_tasks):
# print(per_thread.result())
---------# 注意上面,as_completed(all_tasks) 是等待future對象完成後才執行主線程
---------# 注意下面,wait和 as_completed() 的 做用同樣,就和普通版的join() 類似
for per_thread in all_tasks:
print(per_thread.result())
wait(all_tasks, return_when=ALL_COMPLETED) # 還能夠選FIRST_COMPLETED,待第一個完成後
print('主線程')
方式2: map多線程版
value_list = executor.map(func, list(range(10))) # 返回的直接是map後的序列
for value in value_list:
print(value)
注意:
這個map方式,若是要傳多個參數就涉及到高階函數那節講的偏函數了。
多進程
多進程有2種經過start的那種方式+普通進程池,一樣很是廣泛,此處就不寫了,本身百度一下。
新版進程池 一樣是和上面用同樣的future庫,驚不驚喜。(能夠看出好的程序要向着統一封裝的方向優化)
也許你會驚訝,由於只把thread單詞改成processing就是進程池版本了,就是這麼簡單!!!!!
from time import sleep
import multiprocessing
from concurrent.futures import ProcessPoolExecutor,as_completed,ALL_COMPLETED,wait
executor = ProcessPoolExecutor(max_workers=multiprocessing.cpu_count())
def f():
sleep(15)
return 100
if __name__ == '__main__': # 這句要加
all_tasks = [executor.submit(f) for _ in range(multiprocessing.cpu_count())]
for per_thread in as_completed(all_tasks):
print(per_thread.result())
# for per_thread in all_tasks:
# print(per_thread.result())
# wait(all_tasks, return_when=ALL_COMPLETED)
print('主進程')
# 這就是 futures 模塊 設計思想的魅力
多協程
前言:
也許你記得,函數用到 yield 來代替 return 就變成了 生成器。其特色是代碼片斷斷點式執行。
若是有多個yield, 就能夠本身用程序來切換執行程序。(這就是協程的特色)
推薦:(學習中。。。)
此筆者寫的很好:
https://juejin.im/post/5ccf0d18e51d453b557dc340