python threading-单线程 多线程 主线程 子线程 setDeamon join
python threading-單線程 多線程 主線程 子線程 setDeamon join
- 單線程
- 多線程
- 主線程和子線程
- setDaemon()
- join()
- 測試多線程下程序運行的時間
- 創建多個線程
- 優化子線程
單線程
用單線程 ,做聽音樂和看電影兩件事兒,首先排一下順序。
import timedef music():for i in range(2):print("I was listening to music. %s" %time.ctime())time.sleep(1)def move():for i in range(2):print("I was at the movies. %s" %time.ctime())time.sleep(5)if __name__=='__main__':music()move()print("all over %s" %time.ctime())輸出結果:
I was listening to music. Wed Oct 20 15:42:19 2021 I was listening to music. Wed Oct 20 15:42:20 2021 I was at the movies. Wed Oct 20 15:42:21 2021 I was at the movies. Wed Oct 20 15:42:26 2021 all over Wed Oct 20 15:42:31 2021time.sleep(1)是延時1s的意思。我們先聽了一首音樂,通過for循環來控制音樂的播放了兩次,每首音樂播放需要1秒鐘,sleep()來控制音樂播放的時長。接著我們又看了一場電影,每一場電影需要5秒鐘,通過for循環看兩遍。在整個結束后,輸出當前的時間。
可以發現:整個代碼只能是先干一件事再干一件事。
用時:開始42分19結束是42分31,總耗時為12s。
多線程
cpu同時干多個活都沒問題的,不需要讓一件事一直占著cpu不放;于是,操作系統就進入了多任務時代。
python提供了threading模塊來實現多線程。可以 引入threadring來同時播放音樂和視頻。
import threading import timedef music():for i in range(2):print("I was listening to music. %s" %time.ctime())time.sleep(1)def move():for i in range(2):print("I was at the movies. %s" %time.ctime())time.sleep(5) ''' 創建了threads數組,創建線程t1,使用threading.Thread()方法,在這個方法中調用music方法target=music,把創建好的線程t1裝到threads數組中。接著以同樣的方式創建線程t2,并把t2也裝到threads數組。 ''' threads = [] t1 = threading.Thread(target=music) threads.append(t1) t2 = threading.Thread(target=move) threads.append(t2)if __name__=='__main__':for t in threads:t.setDaemon(True)t.start()print("all over %s" %time.ctime())主線程和子線程
主線程:是執行主(main)方法的線程.
子線程:被Thread包含的“方法體”或者“委托”均為子線程
setDaemon()
當啟動一個線程時設置thread.setDaemon(True),則該線程為守護線程(也可以稱為后臺線程)。表示該線程是不重要的,進程退出時不需要等待這個線程執行完成。這樣做的意義在于:避免子線程無限死循環,導致退不出程序,也就是避免了孤兒進程的出現。
當不設置或者thread.setDaemon(False)時,主進程執行結束時,會等待線程結束。
上述程序如果設置t.setDaemon(False),那么將輸出:
I was listening to music. Wed Oct 20 16:11:27 2021 I was at the movies. Wed Oct 20 16:11:27 2021 all over Wed Oct 20 16:11:27 2021 I was listening to music. Wed Oct 20 16:11:28 2021 I was at the movies. Wed Oct 20 16:11:32 2021可以看到,在主線程進行完之后,也就是輸出all over Wed Oct 20 16:11:27 2021之后,還會繼續執行沒完成的子線程。
如果設置setDaemon(True),那么將輸出:
I was listening to music. Wed Oct 20 16:03:27 2021 I was at the movies. Wed Oct 20 16:03:27 2021 all over Wed Oct 20 16:03:27 2021也就是說,子線程啟動后,父線程也繼續執行下去,當父線程執行完最后一條語句print(“all over %s” %time.ctime())后,沒有等待子線程,直接就退出了,同時子線程也一同結束。
join()
import threading import timedef music():for i in range(2):print("I was listening to music. %s" %time.ctime())time.sleep(1)def move():for i in range(2):print("I was at the movies. %s" %time.ctime())time.sleep(5)threads = [] t1 = threading.Thread(target=music) threads.append(t1) t2 = threading.Thread(target=move) threads.append(t2)if __name__=='__main__':for t in threads:t.setDaemon(True)t.start()for t in threads:t.join()print("all over %s" %time.ctime())運行結果:
I was listening to music. Wed Oct 20 16:21:41 2021 I was at the movies. Wed Oct 20 16:21:41 2021 I was listening to music. Wed Oct 20 16:21:42 2021 I was at the movies. Wed Oct 20 16:21:46 2021 all over Wed Oct 20 16:21:51 2021我們只對上面的程序加了個join()方法,用于等待線程終止。join()的作用是,在子線程完成運行之前,這個子線程的父線程將一直被阻塞。
也就是說,必須等待for循環里的兩個進程都結束后,才去執行主進程。
從執行結果可看到,music 和move 是同時啟動的。
開始時間21分41秒,結束時間為21分51秒,總耗時為10秒。比單線程用時減少了2秒。
測試多線程下程序運行的時間
現在把music的sleep()的時間調整為5秒。
import threading import timedef music():for i in range(2):print("I was listening to music. %s" %time.ctime())time.sleep(5)def move():for i in range(2):print("I was at the movies. %s" %time.ctime())time.sleep(5)threads = [] t1 = threading.Thread(target=music) threads.append(t1) t2 = threading.Thread(target=move) threads.append(t2)if __name__=='__main__':for t in threads:t.setDaemon(True)t.start()for t in threads:t.join()print("all over %s" %time.ctime()) I was listening to music. Wed Oct 20 16:41:59 2021 I was at the movies. Wed Oct 20 16:41:59 2021 I was listening to music. Wed Oct 20 16:42:04 2021 I was at the movies. Wed Oct 20 16:42:04 2021 all over Wed Oct 20 16:42:09 2021可以看到,最后還是用時10s。
如果是用單線程的話,用時將達到5*4=20s。
創建多個線程
從上面例子中發現線程的創建是頗為麻煩的,每創建一個線程都需要創建一個tx(t1、t2、…),如果創建的線程多時候這樣極其不方便。下面對通過例子進行繼續改進:
import threading import timedef music(func):for i in range(2):print("Start music: %s! %s" % (func, time.ctime()))time.sleep(5)def move(func):for i in range(2):print("Start playing: %s! %s" % (func, time.ctime()))time.sleep(5)''' 創建了一個player()函數,這個函數用于判斷播放文件的類型。如果是mp3格式的,我們將調用music()函數,如果是mp4格式的我們調用move()函數。哪果兩種格式都不是那么只能告訴用戶你所提供有文件我播放不了 '''def player(name):r = name.split('.')[1]if r == 'mp3':music(name)else:if r == 'mp4':move(name)else:print("ERROR:The format is not recognized!")''' 創建了一個list的文件列表,注意為文件加上后綴名。然后我們用len(list) 來計算list列表有多少個文件,這是為了幫助我們確定循環次數。 '''list = ['jjj.mp3', 'yyy.mp4']threads = []files = range(len(list))''' 通過一個for循環,把list中的文件添加到線程中數組threads[]中。 '''for i in files:t = threading.Thread(target=player, args=(list[i],))threads.append(t)''' 啟動threads[]線程組,最后打印結束時間。 ''' if __name__ == '__main__':for i in files:threads[i].start()for t in files:threads[i].join()print("all over %s" %time.ctime())運行結果:
Start music: jjj.mp3! Wed Oct 20 17:04:49 2021 Start playing: yyy.mp4! Wed Oct 20 17:04:49 2021 Start playing: yyy.mp4! Wed Oct 20 17:04:54 2021 Start music: jjj.mp3! Wed Oct 20 17:04:54 2021 all over Wed Oct 20 17:04:59 2021其中,split()可以將一個字符串拆分成兩部分,然后取其中的一部分。也就是說,判斷list[i]里面后綴是mp3還是mp4類型的。
>>> x = 'testing.py' >>> s = x.split('.')[1] >>> if s=='py':print(s)py現在向list數組中添加一個文件,程序運行時會自動為其創建一個線程。
優化子線程
我們發現player()用于判斷文件擴展名,然后調用music()和move() ,其實,music()和move()工作是類似的,可以改進一下,不管什么文件都可以播放。
import threading import time''' 創建player()函數,用于接收file和t,用于確定要播放的文件及時長。 ''' def player(file, t):for i in range(2):print("Start playing: %s! %s" % (file, time.ctime()))time.sleep(t)''' 字典list ,用于定義要播放的文件及時長(秒),通過字典的items()方法來循環的取file和t,取到的這兩個值用于創建線程。 '''list = {'jjj.mp3': 3, 'yyy.mp4': 5, 'mmm.mp3': 4}threads = []files = range(len(list))for file, t in list.items():tx = threading.Thread(target=player, args=(file, t))threads.append(tx)if __name__ == '__main__':for i in files:threads[i].start()for t in files:threads[i].join()print("all over %s" %time.ctime())運行結果:
Start playing: jjj.mp3! Wed Oct 20 17:50:43 2021 Start playing: yyy.mp4! Wed Oct 20 17:50:43 2021 Start playing: mmm.mp3! Wed Oct 20 17:50:43 2021 Start playing: jjj.mp3! Wed Oct 20 17:50:46 2021 Start playing: mmm.mp3! Wed Oct 20 17:50:47 2021 Start playing: yyy.mp4! Wed Oct 20 17:50:48 2021 all over Wed Oct 20 17:50:51 2021總結
以上是生活随笔為你收集整理的python threading-单线程 多线程 主线程 子线程 setDeamon join的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: signature=08653706de
- 下一篇: 设备管理器android感叹号,设备管理