python的线程组怎么写_Python学习——Python线程
一、線程創(chuàng)建
1 #方法一:將要執(zhí)行的方法作為參數(shù)傳給Thread的構(gòu)造方法
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)):#定義每個(gè)線程要運(yùn)行的函數(shù)
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:線程組,目前還沒有實(shí)現(xiàn),庫(kù)引用時(shí)提示必須是None
target:要執(zhí)行的方法
name:線程名
args/kwargs:要傳入方法的參數(shù),args和kwargs兩個(gè)參數(shù)其實(shí)是二選一
#實(shí)例方法
isAlive():返回線程是否在運(yùn)行
get/setName(name):獲取/設(shè)置線程名
is/setDaemon(bool):獲取/設(shè)置是否守護(hù)線程。初始值從創(chuàng)建該線程的線程繼承,當(dāng)沒有非守護(hù)線程仍在運(yùn)行時(shí),程序?qū)⒔K止
start():啟動(dòng)線程
join([timeout]):阻塞當(dāng)前上下文環(huán)境的線程。
二、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=('童話鎮(zhèn)',))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=('童話鎮(zhèn)',))
threads.append(t1)
創(chuàng)建了threads數(shù)組,創(chuàng)建線程t1,使用threading.Thread()方法,在這個(gè)方法中調(diào)用music方法target=music,args方法對(duì)music進(jìn)行傳參。?把創(chuàng)建好的線程t1裝到threads數(shù)組中。
接著以同樣的方式創(chuàng)建線程t2,并把t2也裝到threads數(shù)組。
for?t?in?threads:
t.setDaemon(True)
t.start()
最后通過for循環(huán)遍歷數(shù)組。(數(shù)組被裝載了t1和t2兩個(gè)線程)
setDaemon()
setDaemon(True)將線程聲明為守護(hù)線程,必須在start()?方法調(diào)用之前設(shè)置,如果不設(shè)置為守護(hù)線程程序會(huì)被無限掛起。子線程啟動(dòng)后,父線程也繼續(xù)執(zhí)行下去,當(dāng)父線程執(zhí)行完最后一條語句print?"all?over?%s"?%ctime()后,沒有等待子線程,直接就退出了,同時(shí)子線程也一同結(jié)束。
serDeamon(False)(默認(rèn))前臺(tái)線程,主線程執(zhí)行過程中,前臺(tái)線程也在進(jìn)行,主線程執(zhí)行完畢后,等待前臺(tái)線程也執(zhí)行完成后,主線程停止。
運(yùn)行結(jié)果:
I was listening to 童話鎮(zhèn). 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
從執(zhí)行結(jié)果來看,子線程(muisc?、move?)和主線程(print?"all?over?%s"?%ctime())都是同一時(shí)間啟動(dòng),但由于主線程執(zhí)行完結(jié)束,所以導(dǎo)致子線程也終止。
調(diào)整程序:
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()的作用是,在子線程完成運(yùn)行之前,這個(gè)子線程的父線程將一直被阻塞。
join()方法的位置是在for循環(huán)外的,也就是說必須等待for循環(huán)里的兩個(gè)進(jìn)程都結(jié)束后,才去執(zhí)行主進(jìn)程。
運(yùn)行結(jié)果:
1 ############運(yùn)行結(jié)果###################
2 I was listening to 童話鎮(zhèn). Thu Jun 22 23:34:22 2017
3 I was at the 變形金剛! Thu Jun 22 23:34:22 2017
4 I was listening to 童話鎮(zhèn). 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
從結(jié)果的時(shí)間可以看出每首歌之間等待1秒,電影之間等待5秒,但是是同步進(jìn)行的,總的時(shí)間為5秒
三、線程鎖(LOCK,RLOCK)
由于線程之間是進(jìn)行隨機(jī)調(diào)度,并且每個(gè)線程可能只執(zhí)行n條執(zhí)行之后,當(dāng)多個(gè)線程同時(shí)修改同一條數(shù)據(jù)時(shí)可能會(huì)出現(xiàn)臟數(shù)據(jù),所以,出現(xiàn)了線程鎖 - 同一時(shí)刻允許一個(gè)線程執(zhí)行操作。
Lock(指令鎖)是可用的最低級(jí)的同步指令。Lock處于鎖定狀態(tài)時(shí),不被特定的線程擁有。Lock包含兩種狀態(tài)——鎖定和非鎖定,以及兩個(gè)基本的方法。
可以認(rèn)為L(zhǎng)ock有一個(gè)鎖定池,當(dāng)線程請(qǐng)求鎖定時(shí),將線程至于池中,直到獲得鎖定后出池。池中的線程處于狀態(tài)圖中的同步阻塞狀態(tài)。
RLock(可重入鎖)是一個(gè)可以被同一個(gè)線程請(qǐng)求多次的同步指令。RLock使用了“擁有的線程”和“遞歸等級(jí)”的概念,處于鎖定狀態(tài)時(shí),RLock被某個(gè)線程擁有。擁有RLock的線程可以再次調(diào)用acquire(),釋放鎖時(shí)需要調(diào)用release()相同次數(shù)。
可以認(rèn)為RLock包含一個(gè)鎖定池和一個(gè)初始值為0的計(jì)數(shù)器,每次成功調(diào)用 acquire()/release(),計(jì)數(shù)器將+1/-1,為0時(shí)鎖處于未鎖定狀態(tài)。
簡(jiǎn)言之: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')
多次運(yùn)行可能產(chǎn)生混亂。這種場(chǎng)景就是適合使用鎖的場(chǎng)景。
2.使用鎖
1 importthreading2 importtime3
4 num =05 lock =threading.RLock()6
7 #調(diào)用acquire([timeout])時(shí),線程將一直阻塞,
8 #直到獲得鎖定或者直到timeout秒后(timeout參數(shù)可選)。
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')
加上鎖后數(shù)字會(huì)一步步打印出來,不會(huì)因?yàn)閾矶露e(cuò)亂的情況!
四、信號(hào)量(Semaphore)
互斥鎖 同時(shí)只允許一個(gè)線程更改數(shù)據(jù),而Semaphore是同時(shí)允許一定數(shù)量的線程更改數(shù)據(jù) ,比如廁所有3個(gè)坑,那最多只允許3個(gè)人上廁所,后面的人只能等里面有人出來了才能再進(jìn)去。
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個(gè)線程同時(shí)運(yùn)行
12 for i in range(20):13 t = threading.Thread(target=run, args=(i,))14 t.start()
五、事件(event)
Python線程的事件主要用于主線程控制其他線程的執(zhí)行,事件主要提供了三個(gè)方法:set、wait、clear
事件處理的機(jī)制:全局定義了一個(gè)“Flag”,如果“Flag”值為 False,那么當(dāng)程序執(zhí)行 event.wait 方法時(shí)就會(huì)阻塞,如果“Flag”值為True,那么event.wait 方法時(shí)便不再阻塞。
clear:將“Flag”設(shè)置為False
set:將“Flag”設(shè)置為True
用threading.Event實(shí)現(xiàn)線程間的通訊
threading.Event使一個(gè)線程等待其他線程的通知,把這個(gè)Event傳遞到線程對(duì)象中,Event默認(rèn)內(nèi)置了一個(gè)標(biāo)志,初始值為False。
一旦該線程通過wait()方法進(jìn)入等待狀態(tài),直到另一個(gè)線程調(diào)用該Event的set()方法將內(nèi)置標(biāo)志設(shè)置為True時(shí),
該Event會(huì)通知所有等待狀態(tài)的線程恢復(fù)運(yùn)行。
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() #繼續(xù)阻塞
15
16 inp = input('input:')17 if inp == 'true':18 event_obj.set() #喚醒
六、條件(condition)
所謂條件變量,即這種機(jī)制是在滿足特定條件之后,線程才可以訪問相關(guān)的數(shù)據(jù)!
它使用Condition類來完成,由于它也可以像鎖機(jī)制那樣用,所以它也有acquire方法和release方法,而且它還有wait,notify,notifyAll方法
總結(jié)
以上是生活随笔為你收集整理的python的线程组怎么写_Python学习——Python线程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty权威指南_netty官方中文文
- 下一篇: python水平_python水平