Python 多線程 VS 多進程(一)
多線程 vs 多進程
程序:一堆代碼以文本形式存入一個文檔
進程:程序運行的一個狀態
包含地址空間、內容、數據棧等
每個進程由自己完全獨立的運行環境,多進程共享數據是一個問題
線程
一個進程的獨立運行片段,一個進程可以有多個線程
輕量化的進程
一個進程的多個線程間共享數據和上下文運行環境
共享互斥問題
全局解釋器鎖(GTL)
python 代碼的執行是由python 虛擬機進行控制
在主循環中只能有一個控制線程在執行
python 包
thread:有問題,不好用,python3改成了_thread
threading:通行的包
案例01: 順序執行,耗時比較長
''' 利用time函數,生成兩個函數 程序調試 計算總的運行時間 ''' import time def loop1(): # ctime 得到當前時間 print("Start loop 1 at : ",time.ctime()) time.sleep(4) print("End loop 1 at : ", time.ctime()) def loop2(): # ctime 得到當前時間 print("Start loop 2 at : ", time.ctime()) # 睡眠多長時間,單位是秒 time.sleep(2) print("End loop 2 at : ", time.ctime()) def main(): print("Starting at : ", time.ctime()) loop1() loop2() print("All done at : ", time.ctime()) if __name__ == '__main__': main()
Starting at : Tue Aug 13 19:10:31 2019 Start loop 1 at : Tue Aug 13 19:10:31 2019 End loop 1 at : Tue Aug 13 19:10:35 2019 Start loop 2 at : Tue Aug 13 19:10:35 2019 End loop 2 at : Tue Aug 13 19:10:37 2019 All done at : Tue Aug 13 19:10:37 2019
案例02:改用多線程,縮短總時間,使用_thread
''' 利用time函數,生成兩個函數 程序調試 計算總的運行時間 ''' import time import _thread as thread def loop1(): # ctime 得到當前時間 print("Start loop 1 at : ",time.ctime()) time.sleep(4) print("End loop 1 at : ", time.ctime()) def loop2(): # ctime 得到當前時間 print("Start loop 2 at : ", time.ctime()) # 睡眠多長時間,單位是秒 time.sleep(2) print("End loop 2 at : ", time.ctime()) def main(): print("Starting at : ", time.ctime()) # 啟動多線程的意思是用多線程去執行某個函數 # 啟動多線程函數為start_new_thread # 參數兩個,一個是需要運行的函數名,第二個是函數的參數作為元組使用,為空則使用空元組 # 注意,如果函數只有一個參數,需要參數后有一個逗號 thread.start_new_thread(loop1, ()) thread.start_new_thread(loop2, ()) print("All done at : ", time.ctime()) if __name__ == '__main__': main() while True: time.sleep(1)
Starting at : Tue Aug 13 19:14:47 2019 All done at : Tue Aug 13 19:14:47 2019 Start loop 1 at : Tue Aug 13 19:14:47 2019 Start loop 2 at : Tue Aug 13 19:14:47 2019 End loop 2 at : Tue Aug 13 19:14:49 2019 End loop 1 at : Tue Aug 13 19:14:51 2019
案例03:多線程,傳參數
# 利用time延時函數,生成兩個函數 # 利用多線程調用 # 計算總運行時間 # 練習帶參數的多線程啟動方法 import time # 導入多線程包并更名為thread import _thread as thread def loop1(in1): # ctime 得到當前時間 print('Start loop 1 at: ', time.ctime()) # 把參數打印出來 print("我是參數", in1) # 睡眠多長時間,單位是秒 time.sleep(4) print('End loop 1 at: ', time.ctime()) def loop2(in1, in2): # ctime 得到當前時間 print('Start loop 2 at: ', time.ctime()) # 把參數in1 和 in2 打印出來,代表使用 print("我是參數", in1, "和參數", in2) # 睡眠多長時間,單位是秒 time.sleep(4) print('End loop 2 at: ', time.ctime()) def main(): print("Starting at : ", time.ctime()) # 啟動多線程的意思是用多線程去執行某個函數 # 啟動多線程函數為start_new_thread # 參數兩個,一個是需要運行的函數名,第二個是函數的參數作為元組使用,為空則使用空元組 # 注意,如果函數只有一個參數,需要參數后有一個逗號 thread.start_new_thread(loop1, ("王老大", )) thread.start_new_thread(loop2, ("王大鵬", "王曉鵬")) print("All done at : ", time.ctime()) if __name__ == '__main__': main() # 一定要有while語句 # 因為啟動多線程后本程序就作為主線程存在 # 如果主線程執行完畢,則子線程可能也需要終止 while True: time.sleep(10)
Starting at : Tue Aug 13 19:17:10 2019 All done at : Tue Aug 13 19:17:10 2019 Start loop 1 at: Tue Aug 13 19:17:10 2019 我是參數 王老大 Start loop 2 at: Tue Aug 13 19:17:10 2019 我是參數 王大鵬 和參數 王曉鵬 End loop 1 at: Tue Aug 13 19:17:14 2019 End loop 2 at: Tue Aug 13 19:17:14 2019
threading的使用
直接利用threading.Thread生成Thread實例
t = threading.Thread(target=xxx, args=(xxx, ))
t.start(): 啟動多線程
t.join(): 等待多線程執行完成
案例04
# 利用time延時函數,生成兩個函數 # 利用多線程調用 # 計算總運行時間 # 練習帶參數的多線程啟動方法 import time # 導入多線程包并更名為thread import threading def loop1(in1): # ctime 得到當前時間 print('Start loop 1 at: ', time.ctime()) # 把參數打印出來 print("我是參數", in1) # 睡眠多長時間,單位是秒 time.sleep(4) print('End loop 1 at: ', time.ctime()) def loop2(in1, in2): # ctime 得到當前時間 print('Start loop 2 at: ', time.ctime()) # 把參數in1 和 in2 打印出來,代表使用 print("我是參數", in1, "和參數 ", in2) # 睡眠多長時間,單位是秒 time.sleep(2) print('End loop 2 at: ', time.ctime()) def main(): print("Starting at: ", time.ctime()) # 生成threading.Thread實例 t1 = threading.Thread(target=loop1, args=("王老大",)) t1.start() t2 = threading.Thread(target=loop2, args=("王大鵬", "王小鵬")) t2.start() print("All done at: ", time.ctime()) if __name__ == '__main__': main() # 一定要有while語句 # 因為啟動多線程后本程序就作為主線程存在 # 如果主線程執行完畢,則子線程可能也需要終止 while True: time.sleep(10)
Starting at: Tue Aug 13 19:19:42 2019 Start loop 1 at: Tue Aug 13 19:19:42 2019 我是參數 王老大 Start loop 2 at: All done at: Tue Aug 13 19:19:42 2019 Tue Aug 13 19:19:42 2019 我是參數 王大鵬 和參數 王小鵬 End loop 2 at: Tue Aug 13 19:19:44 2019 End loop 1 at: Tue Aug 13 19:19:46 2019
案例05:加入join后比較案例04的結果的異同
# 利用time延時函數,生成兩個函數 # 利用多線程調用 # 計算總運行時間 # 練習帶參數的多線程啟動方法 import time # 導入多線程包并更名為thread import threading def loop1(in1): # ctime 得到當前時間 print('Start loop 1 at: ', time.ctime()) # 把參數打印出來 print("我是參數", in1) # 睡眠多長時間,單位是秒 time.sleep(4) print('End loop 1 at: ', time.ctime()) def loop2(in1, in2): # ctime 得到當前時間 print('Start loop 2 at: ', time.ctime()) # 把參數in1 和 in2 打印出來,代表使用 print("我是參數", in1, "和參數 ", in2) # 睡眠多長時間,單位是秒 time.sleep(2) print('End loop 2 at: ', time.ctime()) def main(): print("Starting at: ", time.ctime()) # 生成threading.Thread實例 t1 = threading.Thread(target=loop1, args=("王老大",)) t1.start() t2 = threading.Thread(target=loop2, args=("王大鵬", "王小鵬")) t2.start() t1.join() t2.join() print("All done at: ", time.ctime()) if __name__ == '__main__': main() # 一定要有while語句 # 因為啟動多線程后本程序就作為主線程存在 # 如果主線程執行完畢,則子線程可能也需要終止 while True: time.sleep(10)
Starting at: Tue Aug 13 19:21:58 2019 Start loop 1 at: Tue Aug 13 19:21:58 2019 我是參數 王老大 Start loop 2 at: Tue Aug 13 19:21:58 2019 我是參數 王大鵬 和參數 王小鵬 End loop 2 at: Tue Aug 13 19:22:00 2019 End loop 1 at: Tue Aug 13 19:22:02 2019 All done at: Tue Aug 13 19:22:02 2019
守護線程-daemon
如果在程序中將子線程設置成守護線程,則子線程會在主線程結束的時候自動退出
一般認為,守護線程不重要或者不允許離開主線程獨立運行
守護線程案例能否有效果跟環境相關
案例06非守護線程
import time import threading def fun(): print("Start fun") time.sleep(2) print("end fun") print("Main thread") t1 = threading.Thread(target=fun, args=() ) t1.start() time.sleep(1) print("Main thread end")
Main thread Start fun Main thread end end fun
案例07守護線程
import time import threading def fun(): print("Start fun") time.sleep(2) print("end fun") print("Main thread") t1 = threading.Thread(target=fun, args=() ) # 啟動之前設置 t1.setDaemon(True) # t1.daemon = True t1.start() time.sleep(1) print("Main thread end")
Main thread Start fun Main thread end
線程常用屬性
threading.currentThread:返回當前線程變量
threading.enumerate:返回一個包含正在運行的線程的list,正在運行的線程指的是線程啟動后,結束前的狀態
threading.activeCount: 返回正在運行的線程數量,效果跟 len(threading.enumerate)相同
thr.setName: 給線程設置名字
thr.getName: 得到線程的名字
案例08
import time import threading def loop1(): # ctime 得到當前時間 print("Start loop 1 at : ",time.ctime()) time.sleep(6) print("End loop 1 at : ", time.ctime()) def loop2(): # ctime 得到當前時間 print("Start loop 2 at : ",time.ctime()) time.sleep(1) print("End loop 2 at : ", time.ctime()) def loop3(): # ctime 得到當前時間 print("Start loop 3 at : ",time.ctime()) time.sleep(5) print("End loop 3 at : ", time.ctime()) def main(): print("Starting at: ", time.ctime()) # 生成threading.Thread實例 t1 = threading.Thread(target=loop1, args=( )) # setName是給每一個子線程設置一個名字 t1.setName("THR_1") t1.start() t2 = threading.Thread(target=loop2, args=( )) t2.setName("THR_2") t2.start() t3 = threading.Thread(target=loop3, args=( )) t3.setName("THR_3") t3.start() # 預期3秒后,thread2已經結束 time.sleep(3) # enumerate 得到正在運行子線程,即子線程1和子線程3 for thr in threading.enumerate(): # getName能夠得到線程的名字 print("正在運行的線程名字是: {0}".format(thr.getName())) print("正在運行的子線程數量為: {0}".format(threading.activeCount())) print("All done at: ", time.ctime()) if __name__ == '__main__': main() # 一定要有while語句 # 因為啟動多線程后本程序就作為主線程存在 # 如果主線程執行完畢,則子線程可能也需要終止 while True: time.sleep(10)
Starting at: Tue Aug 13 19:28:20 2019 Start loop 1 at : Tue Aug 13 19:28:20 2019 Start loop 2 at : Tue Aug 13 19:28:20 2019 Start loop 3 at : Tue Aug 13 19:28:20 2019 End loop 2 at : Tue Aug 13 19:28:21 2019 正在運行的線程名字是: MainThread 正在運行的線程名字是: THR_1 正在運行的線程名字是: THR_3 正在運行的子線程數量為: 3 All done at: Tue Aug 13 19:28:23 2019 End loop 3 at : Tue Aug 13 19:28:25 2019 End loop 1 at : Tue Aug 13 19:28:26 2019
直接繼承自threading.Thread
直接繼承Thread
重寫run函數
類實例可以直接運行
案例09
import threading import time # 1. 類需要繼承來自threading.Thread class MyThread(threading.Thread): def __init__(self, arg): super().__init__() self.arg = arg # 2. 必須重寫run函數,run函數代表的是真正執行的功能 def run(self): time.sleep(2) print("The args for this class is {0}".format(self.arg)) for i in range(5): t = MyThread(i) t.start() t.join() print("Main thread is done!!!!!!!!")
The args for this class is 0 The args for this class is 1 The args for this class is 2 The args for this class is 3 The args for this class is 4 Main thread is done!!!!!!!!
案例10 工業風案例
import threading from time import sleep, ctime loop = [4, 2] class ThreadFunc: def __init__(self, name): self.name = name def loop(self, nloop, nsec): ''' :param nloop:loop函數的名稱 :param nsec:系統休眠時間 :return: ''' print('Start loop', nloop, 'at ', ctime()) sleep(nsec) print('Done loop', nloop, 'at ', ctime()) def main(): print("Starting at: ", ctime()) # ThreadFunc("loop").loop 跟以下兩個式子相等 # t = ThreadFunc("loop") # t.loop # 以下t1 和 t2的定義方式相等 t = ThreadFunc("loop") t1 = threading.Thread( target=t.loop, args=("LOOP1", 4)) # 下面這種寫法更西方人,工業化一點 t2 = threading.Thread( target=ThreadFunc('loop').loop, args=('LOOP2', 2)) # 常見錯誤寫法 # t1 = threading.Thread(target=ThreadFunc('loop').loop(100,4)) # t2 = threading.Thread(target=ThreadFunc('loop').loop(100,2)) t1.start() t2.start() t1.join() t2.join() print("All done at: ", ctime()) if __name__ == '__main__': main() # 一定要有while語句 # 因為啟動多線程后本程序就作為主線程存在 # 如果主線程執行完畢,則子線程可能也需要終止 while True: sleep(10)
Starting at: Tue Aug 13 19:31:16 2019 Start loop LOOP1 at Tue Aug 13 19:31:16 2019 Start loop LOOP2 at Tue Aug 13 19:31:16 2019 Done loop LOOP2 at Tue Aug 13 19:31:18 2019 Done loop LOOP1 at Tue Aug 13 19:31:20 2019 All done at: Tue Aug 13 19:31:20 2019
Python 任務調度 多線程
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。