總結的太到位:python 多線程系列詳解

檸檬班軟件測試 發佈 2022-07-28T05:55:18.261907+00:00

前言:上vip課的時候每次講到框架的執行,就會有好學的同學問用多線程怎麼執行,然後我每次都會說在測開課程會詳細講解,這並不是套路,因為如果你不理解多線程,不清楚什麼時候該用什麼時候不該用,就會適得其反。今天我們就來聊一聊多線程這個燙手的山芋。

前言:


上vip課的時候每次講到框架的執行,就會有好學的同學問用多線程怎麼執行,然後我每次都會說在測開課程會詳細講解,這並不是套路,因為如果你不理解多線程,不清楚什麼時候該用什麼時候不該用,就會適得其反。今天我們就來聊一聊多線程這個燙手的山芋。


一、python執行慢的原因


1、動態類型語言,邊解釋邊執行。


2、GIL鎖無法使用多核CPU並發執行。


二、什麼是GIL鎖


1、全局解釋器鎖(Global Interpreter Lock),是電腦程式設計語言計時器用於同步線程的一種機制,它使得任何時刻僅有一個線程在執行。
即使在多核CPU上,使用GIL的解釋器也只允許同一時間執行一個線程。


2、你可以理解為這是python設計上的一個Bug,但是因為重構成本太高,龜叔也沒打算修復了。


3、那麼多線程就沒有用了嗎?當然不是,多線程可以用於IO密集型任務。

三、CPU密集型


阿里雲開發者社區的解釋:CPU密集型(CPU-bound) CPU密集型也叫計算密集型,指的是系統的硬碟、內存性能相對CPU要好很多,此時,系統運作大部分的狀況是CPU Loading 100%,CPU要讀/寫I/O(硬碟/內存),I/O在很短的時間就可以完成,而CPU還有許多運算要處理,CPU Loading很高。


說人話:做某件事情的時候CPU很忙,磁碟/內存讀取很閒,這個事情就叫CPU密集型任務。

四、IO密集型


阿里雲開發者社區的解釋:IO密集型指的是系統的CPU性能相對硬碟、內存要好很多,此時,系統運作,大部分的狀況是CPU在等I/O (硬碟/內存) 的讀/寫操作,此時CPU Loading並不高。


說人話:做某件事情的時候磁碟/內存讀取很忙,CPU很閒,這個事情就叫IO密集型任務。

五、什麼是多線程


百度百科的解釋:多線程(multithreading),是指從軟體或者硬體上實現多個線程並發執行的技術。


六、多線程使用場景


1、用於IO密集型任務



七、進入主題上代碼


import requests
import time
import Threading


#幹活函數,請求測試派,其他的啥都不干
def get_url(url):
    requests.get(url=url)


#單線程實現,訪問測試派50次
def single(url):
    for i in range(50):
        get_url(url)


#多線程實現,訪問測試派50次
def create_multi(url):
    threads = []
    for i in range(50):
        #創建子線程
        th = threading.Thread(target=get_url,args=(url,))
        threads.append(th)
    #啟動子線程
    for val in threads:
        val.start()
    #主線程等待子線程執行結束再結束
    for val in threads:
        val.join()


if __name__ == '__main__':
    url = "http://testingpai.com/recent"
    #單線程執行時間統計
    start = time.time()
    single(url)
    end=time.time()
    print("單線程耗時:",end - start)
    print("="*30)
    #多線程執行時間統計
    start = time.time()
    create_multi(url)
    end=time.time()
    print("多線程耗時:",end - start)


輸出:
單線程耗時:27.86112666130066
==============================
多線程耗時: 19.54499316215515


►►►

多線程的創建方式


上面我們講了多線程的使用場景,通過一個簡單的例子了解了多線程在IO密集型任務中確實能提高代碼執行效率,接下來我們聊一聊多線程的創建。


一、實例化Thread類創建


import requests
import threading


#幹活函數,請求測試派,其他的啥都不干
def get_url(url):
    requests.get(url=url)


if __name__ == '__main__':
    url = "http://testingpai.com/recent"
    threads = []
    for i in range(50):
        #創建子線程
        th = threading.Thread(target=get_url,args=(url,))
        threads.append(th)
    #啟動子線程
    for val in threads:
        val.start()
    #主線程等待子線程執行結束再結束
    for val in threads:
        val.join()


二、繼承Thread重寫run方法創建


import requests
import threading


class TestThreading(threading.Thread):
    def __init__(self):
        #調用父類初始化函數進行必要的初始化
        super().__init__()


    #重寫run方法
    def run(self):
        thread_name = threading.current_thread().name
        thread_id = threading.current_thread().ident
        print('子線程id={},子線程名稱={}:'.format(thread_id, thread_name))
        print("幹活的函數邏輯寫在這裡")
        res = requests.get(url="http://testingpai.com/recent")
        print(res)


if __name__ == '__main__':
    #啟動子線程
    for i in range(3):
        th = TestThreading()
        th.start()
關鍵字: