python3 多執行緒
多執行緒的優點:①使用執行緒可以吧佔據長時間的程式中的任務放到後臺去處理
②用於介面可以更加吸引人,比如使用者點選了一個按鈕去觸發某些事件的處理,可以彈出一個進度條來顯示處理的進度
③程式的執行速度可能加快
④在一些等待的任務實現上如使用者輸入、檔案讀寫和網路收發資料等,執行緒就發揮作用了。在這種情況下我們可以釋放一些珍貴的資源如記憶體佔用等等。
每個獨立的執行緒有一個程式執行的入口、順序執行序列和程式的出口。但是執行緒不能獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒進行控制。
每個執行緒都有他自己的一組暫存器稱為執行緒的上下文,該上下文反映了執行緒上次執行該執行緒的CPU暫存器的狀態。
指令指標和堆疊指標暫存器是執行緒上下文中兩個最重要的暫存器,執行緒總是在程序得到上下文中執行的,這些地址都用於標誌擁有執行緒的程序地址空間中的記憶體。
注意:①執行緒可以被搶佔(中斷)
②在其他執行緒正在執行時,執行緒可以暫時擱置(也稱為睡眠)---這就是執行緒的退讓
執行緒可以分為:①核心執行緒:由作業系統核心 建立和撤銷
②使用者執行緒:不需要核心支援而在使用者程式中實現的執行緒
Python3多執行緒中常用的兩個模組未:①_thread ② threading(推薦使用)
其中,thread模組已經被廢棄,使用者可以使用threading替代,所以在Python3中不能再使用 thread模組。為了相容性,Python3將 thread重新命名為 _thread。
threading模組除了包含_thread模組中的所有方法外,還提供了額外的方法:
①threading.currentThread(): 返回當前的執行緒變數
②threading.enumerate():返回一個包含正在執行的執行緒的list。正在執行指執行緒啟動後、結束前,不包括啟動前和終止後的執行緒。
③threading.activeCount(): 返回正在執行的執行緒數量,與len(threading.enumerate()有相同的效果。
除了使用方法外,執行緒模組提供了thread類來處理執行緒,thread類提供瞭如下方法:
①run():用以表示執行緒活動的方法
②start(): 啟動執行緒活動
③join([time]): 等待至執行緒中止。阻塞執行緒直至執行緒的join()方法被呼叫中止-正常 退出或者丟擲未處理的異常-或者是可選的超時發生
④isAlive(): 返回執行緒是否活動
⑤getName(): 返回執行緒名
⑥setName(): 設定執行緒名
一個無執行緒程式:
import timestart = time.time() people = 500 # 假設有500個人 def action(num): global people while people>0: people -= 50 # 每次運輸50人 print("車輛編號:%d, 當前車站人數:%d" %(num, people)) time.sleep(1) num = 1 # 車輛編號 action(num) end = time.time() print("Duration time: %0.3f" %(end-start))
結果:
車輛編號:1, 當前車站人數:450 車輛編號:1, 當前車站人數:400 車輛編號:1, 當前車站人數:350 車輛編號:1, 當前車站人數:300 車輛編號:1, 當前車站人數:250 車輛編號:1, 當前車站人數:200 車輛編號:1, 當前車站人數:150 車輛編號:1, 當前車站人數:100 車輛編號:1, 當前車站人數:50 車輛編號:1, 當前車站人數:0 Duration time: 10.001
一個單執行緒程式:
import threading import timestart = time.time() people = 500 # 假設有500個人 def action(num): global people while people>0: people -= 50 # 每次運輸50人 print("車輛編號:%d, 當前車站人數:%d" %(num, people)) time.sleep(1) num = 1 # 車輛編號 vehicle = threading.Thread(target=action, args=(num,)) # 新建車輛 vehicle.start() # 啟動車輛 vehicle.join() # 檢查到站車輛 end = time.time() print("Duration time: %0.3f" %(end-start))
結果:
車輛編號:1, 當前車站人數:450 車輛編號:1, 當前車站人數:400 車輛編號:1, 當前車站人數:350 車輛編號:1, 當前車站人數:300 車輛編號:1, 當前車站人數:250 車輛編號:1, 當前車站人數:200 車輛編號:1, 當前車站人數:150 車輛編號:1, 當前車站人數:100 車輛編號:1, 當前車站人數:50 車輛編號:1, 當前車站人數:0 Duration time: 10.001
一個多執行緒程式(傳遞物件方式建立執行緒):
# -*- coding: utf-8 -* import threading import time people = 500 # 假設有500個人 def action(num): global people while people>0: people -= 50 # 每次運輸50人 print("車輛編號:%d, 當前車站人數:%d" %(num, people)) time.sleep(1) start = time.time() vehicles = [] # 新建車輛組 for num in range(5): vehicle = threading.Thread(target=action, args=(num,)) # 新建車輛 vehicles.append(vehicle) # 新增車輛到車輛組中 for vehicle in vehicles: vehicle.start() # 分別啟動車輛 for vehicle in vehicles: vehicle.join() # 分別檢查到站車輛 end = time.time() print("Duration time: %0.3f" % (end-start))
執行結果:
車輛編號:0, 當前車站人數:450 車輛編號:1, 當前車站人數:400 車輛編號:2, 當前車站人數:350 車輛編號:3, 當前車站人數:300 車輛編號:4, 當前車站人數:250 車輛編號:2, 當前車站人數:200 車輛編號:1, 當前車站人數:150 車輛編號:0, 當前車站人數:100 車輛編號:3, 當前車站人數:50 車輛編號:4, 當前車站人數:0 Duration time: 2.001
一個多執行緒程式(覆蓋子類的方式):
# -*- coding: utf-8 -* import threading import time people = 500 class MyThread(threading.Thread): def __init__(self, num): super(MyThread, self).__init__() self.num = num def run(self): global people while people > 0: people -= 50 print("車輛編號:%d, 當前車站人數:%d " % (self.num, people)) time.sleep(1) start = time.time() vehicles = [] # 新建車輛組 for num in range(5): # 設定車輛數 vehicle = MyThread(num) # 新建車輛 vehicles.append(vehicle) # 新增車輛到車輛組中 vehicle.start() #啟動車輛 for vehicle in vehicles: vehicle.join() # 分別檢查到站車輛 end = time.time() print("Duration time: %0.3f" % (end-start))
結果:
車輛編號:0, 當前車站人數:450 車輛編號:1, 當前車站人數:400 車輛編號:2, 當前車站人數:350 車輛編號:3, 當前車站人數:300 車輛編號:4, 當前車站人數:250 車輛編號:0, 當前車站人數:200 車輛編號:2, 當前車站人數:150 車輛編號:3, 當前車站人數:100車輛編號:1, 當前車站人數:50 車輛編號:4, 當前車站人數:0 Duration time: 2.003
結果分析: ①通過顯示結果可以發現,不使用執行緒的程式和使用單執行緒的程式執行時間是一樣的,這是因為我們正常執行一個指令碼,本質上就是單執行緒執行。
②建立多執行緒的兩種方法執行時間也是一樣的,因為最終都是交給thread類來處理,自行選擇即可。
③多執行緒執行時間明顯比單線快大概5倍,從理論上來說是和執行緒數成正比的,但是實際應用中並非執行緒越多就越好,因為執行緒越多消耗的資源也就越多。
注意:①建立執行緒物件後,必須通過呼叫執行緒的start()方法啟動其活動,這將在單獨的控制執行緒中呼叫run()方法
②一旦執行緒的活動開始,執行緒就是被認為是“活著的”,當run()方法終止時,它會停止活動,或者引發異常
③執行緒可以呼叫is_alive()方法測試是否處於活動狀態,其他執行緒可以呼叫執行緒的join()方法,這將阻塞呼叫執行緒,直到呼叫其join()方法的執行緒終止
④執行緒有一個名稱,這個名稱可以傳遞給建構函式,並通過name屬性讀取或更改
⑤執行緒可以標記為“守護程式執行緒”,這個標誌的意義在於,當只剩下守護程序執行緒時,整個Python程式都會推出,可以通過守護程式屬性設定該標誌
更多請看: https://www.cnblogs.com/leozhanggg/p/10335098.html