python的线程组怎么写_Python学习——Python线程
一、線程創建
1 #方法一:將要執行的方法作為參數傳給Thread的構造方法
2 importthreading3 importtime4
5 defshow(arg):6 time.sleep(2)7 print('thread' +str(arg))8
9 for i in range(10):10 t = threading.Thread(target=show,args=(i,))11 time.sleep(2)12 t.start()13
14 #方法2:從Thread繼承,并重寫run()
15 classMyThread(threading.Thread):16 def __init__(self,num):17 threading.Thread.__init__(self)18 self.num =num19
20 def run(self)):#定義每個線程要運行的函數
21 print("running on number:%s" %self.num)22 time.sleep(3)23
24
25 if __name__ == '__main__':26 t1 = MyThread(1)27 t2 = MyThread(2)28 t1.start()29 time.sleep(3)30 t2.start()
注解:
Thread(group=None,target=None,name=None,args=(),kwargs={})
group:線程組,目前還沒有實現,庫引用時提示必須是None
target:要執行的方法
name:線程名
args/kwargs:要傳入方法的參數,args和kwargs兩個參數其實是二選一
#實例方法
isAlive():返回線程是否在運行
get/setName(name):獲取/設置線程名
is/setDaemon(bool):獲取/設置是否守護線程。初始值從創建該線程的線程繼承,當沒有非守護線程仍在運行時,程序將終止
start():啟動線程
join([timeout]):阻塞當前上下文環境的線程。
二、Python多線程用法
1 importthreading2 from time importctime,sleep3
4 defmusic(func):5 for i in range(2):6 print("I was listening to %s. %s" %(func,ctime()))7 sleep(1)8 defmove(func):9 for i in range(2):10 print("I was at the %s! %s" %(func,ctime()))11 sleep(5)12
13 threads =[]14 t1 = threading.Thread(target=music,args=('童話鎮',))15 threads.append(t1)16 t2 = threading.Thread(target=move,args=('變形金剛',))17 threads.append(t2)18
19 if __name__ == '__main__':20 for t inthreads:21 t.setDaemon(True)22 t.start()23
24 print("all over %s" %ctime())
注:
threads?=?[]
t1?=?threading.Thread(target=music,args=('童話鎮',))
threads.append(t1)
創建了threads數組,創建線程t1,使用threading.Thread()方法,在這個方法中調用music方法target=music,args方法對music進行傳參。?把創建好的線程t1裝到threads數組中。
接著以同樣的方式創建線程t2,并把t2也裝到threads數組。
for?t?in?threads:
t.setDaemon(True)
t.start()
最后通過for循環遍歷數組。(數組被裝載了t1和t2兩個線程)
setDaemon()
setDaemon(True)將線程聲明為守護線程,必須在start()?方法調用之前設置,如果不設置為守護線程程序會被無限掛起。子線程啟動后,父線程也繼續執行下去,當父線程執行完最后一條語句print?"all?over?%s"?%ctime()后,沒有等待子線程,直接就退出了,同時子線程也一同結束。
serDeamon(False)(默認)前臺線程,主線程執行過程中,前臺線程也在進行,主線程執行完畢后,等待前臺線程也執行完成后,主線程停止。
運行結果:
I was listening to 童話鎮. Thu Jun 22 23:23:07 2017
I was at the 變形金剛! Thu Jun 22 23:23:07 2017
all over Thu Jun 22 23:23:07 2017
從執行結果來看,子線程(muisc?、move?)和主線程(print?"all?over?%s"?%ctime())都是同一時間啟動,但由于主線程執行完結束,所以導致子線程也終止。
調整程序:
1 if __name__ == '__main__':2 for t inthreads:3 t.setDaemon(True)4 t.start()5
6 t.join()7
8 print "all over %s" %ctime()
加了join()方法,用于等待線程終止。join()的作用是,在子線程完成運行之前,這個子線程的父線程將一直被阻塞。
join()方法的位置是在for循環外的,也就是說必須等待for循環里的兩個進程都結束后,才去執行主進程。
運行結果:
1 ############運行結果###################
2 I was listening to 童話鎮. Thu Jun 22 23:34:22 2017
3 I was at the 變形金剛! Thu Jun 22 23:34:22 2017
4 I was listening to 童話鎮. Thu Jun 22 23:34:23 2017
5 I was at the 變形金剛! Thu Jun 22 23:34:27 2017
6 all over Thu Jun 22 23:34:32 2017
從結果的時間可以看出每首歌之間等待1秒,電影之間等待5秒,但是是同步進行的,總的時間為5秒
三、線程鎖(LOCK,RLOCK)
由于線程之間是進行隨機調度,并且每個線程可能只執行n條執行之后,當多個線程同時修改同一條數據時可能會出現臟數據,所以,出現了線程鎖 - 同一時刻允許一個線程執行操作。
Lock(指令鎖)是可用的最低級的同步指令。Lock處于鎖定狀態時,不被特定的線程擁有。Lock包含兩種狀態——鎖定和非鎖定,以及兩個基本的方法。
可以認為Lock有一個鎖定池,當線程請求鎖定時,將線程至于池中,直到獲得鎖定后出池。池中的線程處于狀態圖中的同步阻塞狀態。
RLock(可重入鎖)是一個可以被同一個線程請求多次的同步指令。RLock使用了“擁有的線程”和“遞歸等級”的概念,處于鎖定狀態時,RLock被某個線程擁有。擁有RLock的線程可以再次調用acquire(),釋放鎖時需要調用release()相同次數。
可以認為RLock包含一個鎖定池和一個初始值為0的計數器,每次成功調用 acquire()/release(),計數器將+1/-1,為0時鎖處于未鎖定狀態。
簡言之:Lock屬于全局,Rlock屬于線程。
1,未使用鎖
1 importthreading2 importtime3
4 num =05
6 defshow(arg):7 globalnum8 time.sleep(1)9 num +=1
10 print(num)11
12 for i in range(10):13 t = threading.Thread(target=show, args=(i,))14 t.start()15
16 print('main thread stop')
多次運行可能產生混亂。這種場景就是適合使用鎖的場景。
2.使用鎖
1 importthreading2 importtime3
4 num =05 lock =threading.RLock()6
7 #調用acquire([timeout])時,線程將一直阻塞,
8 #直到獲得鎖定或者直到timeout秒后(timeout參數可選)。
9 #返回是否獲得鎖。
10 defshow(arg):11 lock.acquire()12 globalnum13 time.sleep(1)14 num +=1
15 print(num)16 lock.release()17
18 for i in range(10):19 t = threading.Thread(target=show, args=(i,))20 t.start()21
22 print('main thread stop')
加上鎖后數字會一步步打印出來,不會因為擁堵而錯亂的情況!
四、信號量(Semaphore)
互斥鎖 同時只允許一個線程更改數據,而Semaphore是同時允許一定數量的線程更改數據 ,比如廁所有3個坑,那最多只允許3個人上廁所,后面的人只能等里面有人出來了才能再進去。
1 importthreading, time2
3 defrun(n):4 semaphore.acquire()5 time.sleep(3)6 print("run the thread: %s" %n)7 semaphore.release()8
9 if __name__ == '__main__':10 num =011 semaphore = threading.BoundedSemaphore(5) #最多允許5個線程同時運行
12 for i in range(20):13 t = threading.Thread(target=run, args=(i,))14 t.start()
五、事件(event)
Python線程的事件主要用于主線程控制其他線程的執行,事件主要提供了三個方法:set、wait、clear
事件處理的機制:全局定義了一個“Flag”,如果“Flag”值為 False,那么當程序執行 event.wait 方法時就會阻塞,如果“Flag”值為True,那么event.wait 方法時便不再阻塞。
clear:將“Flag”設置為False
set:將“Flag”設置為True
用threading.Event實現線程間的通訊
threading.Event使一個線程等待其他線程的通知,把這個Event傳遞到線程對象中,Event默認內置了一個標志,初始值為False。
一旦該線程通過wait()方法進入等待狀態,直到另一個線程調用該Event的set()方法將內置標志設置為True時,
該Event會通知所有等待狀態的線程恢復運行。
1 importthreading2
3 defdo(event):4 print('start')5 event.wait()6 print('end')7
8 event_obj =threading.Event()9
10 for i in range(10):11 t = threading.Thread(target=do, args=(event_obj,))12 t.start()13
14 event_obj.clear() #繼續阻塞
15
16 inp = input('input:')17 if inp == 'true':18 event_obj.set() #喚醒
六、條件(condition)
所謂條件變量,即這種機制是在滿足特定條件之后,線程才可以訪問相關的數據!
它使用Condition類來完成,由于它也可以像鎖機制那樣用,所以它也有acquire方法和release方法,而且它還有wait,notify,notifyAll方法
總結
以上是生活随笔為你收集整理的python的线程组怎么写_Python学习——Python线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty权威指南_netty官方中文文
- 下一篇: python水平_python水平