python threading模塊(全)

        一、線程與進程的介紹參考之前寫的VC++的多線程與互斥對象:

 https://blog.csdn.net/Gordennizaicunzai/article/details/52268343

        二、python全局解析器鎖(GIL)。

        python代碼相對於其它語言在多線程效率上有個“先天性缺陷”——python有個虛擬機(又名解析器主循環)對代碼進行執行控制,在解析器主循環中單位時間內只能有一個控制線在執行。意思是任意時刻只能有一個程序在運行,即使內存中有多個程序。python通過GIL對虛擬機進行訪問:

        1、設置GIL。

        2、切換進一個線程去運行。

        3、執行下面操作之一:

                a. 指定數量的字節碼指令。

                b. 線程主動讓出控制權(可以調用time.sleep(0))來完成。

        4、把線程設置回睡眠狀態(切換退出線程)。

        5、解鎖GIL。

        6、重複1~5。

        對效率要求非常高的python開發中,傾向於這樣設計:

        IO密集型(不用CPU)——多線程

        計算密集型(用CPU)——多進程

        三、Threading模塊的對象。

對象 描述
Thread 表示一個執行線程的對象。
Lock 鎖原語對象(和thread模塊中的鎖一樣)。
Rlock 可重入鎖對象,使單一線程可以(再次)獲得已持有的鎖(遞歸鎖)。
Condition 條件變量對象,使得一個線程等待另一個線程滿足特定的“條件”,比如改變狀態或某個數據值。
Event 條件變量的通用版本,任意數量的線程等待某個事件的發生,在該事件發生後所有線程將被激活。
Semaphore 爲線程間共享的有限資源提供了一個“計數器”,如果沒有可用資源時會被阻塞。
BoundedSemaphore 與Semahore相似,不過它不允許超過初始值。
Timer 與Thread相似,不過它要在運行前等待一段時間。
Barrier 創建一個“障礙”,必須達到指定數量的線程後纔可以繼續。

        3.1、Thread類。

屬性或方法 描述
name 線程名,可以用直接賦值進行修改,如Thread.name = 'T1'。
ident 線程的標識符。
daemon 布爾標誌,True爲守護線程,False則不是,可以直接賦值,如Thread.daemon = True。
_init_(group=None, tatget=None, name=None, args=(),
kwargs={}, verbose=None, daemon=None)
實例化一個線程對象,需要有一個可調用的target,以及其參數args(傳元祖等iterable)或kwargs。還可以傳遞name或group參數,不過後者還未實現。此外,verbose標誌也是可以接受的。而daemon的值將會設定thread.daemon屬性/標誌。
start() 開始執行該線程。
run() 定義線程功能的方法(通常在子類中被應用開發者重寫)。
join(timeout=None) 直至啓動的線程終止之前一直掛起:除非給出了timeout(秒),否則會一直阻塞。自旋鎖。
is_alive() 布爾標誌,表示這個線程是否還活着。
>>> import threading
>>> import time
>>> 
>>> def thread1(tickets):
	if tickets <= 0:
		print("輸入的票數不能小於等於0")
		return False
	while tickets > 0:
		print("thread1 sell ticket : %d" % tickets)
		tickets -= 1
		time.sleep(1)
	return True

>>> t1 = threading.Thread(target=thread1,args=(50,))
>>> t1
<Thread(Thread-4, initial)>
>>> t1.name
'Thread-4'
>>> t1.name = 'T1'
>>> t1
<Thread(T1, initial)>
>>> t1.name
'T1'
>>> t1.daemon
False
>>> t1.daemon = True
>>> t1.daemon
True
>>> t1.is_alive()
False
>>> t1.start()
thread1 sell ticket : 50
>>> 
thread1 sell ticket : 49
thread1 sell ticket : 48
thread1 sell ticket : 47
thread1 sell ticket : 46
thread1 sell ticket : 45t1.is_alive()
True

>>> thread1 sell ticket : 44
thread1 sell ticket : 43
thread1 sell ticket : 42
thread1 sell ticket : 41
thread1 sell ticket : 40
thread1 sell ticket : 39
thread1 sell ticket : 38
print('Y')
Y
>>> thread1 sell ticket : 37
thread1 sell ticket : 36
thread1 sell ticket : 35
thread1 sell ticket : 34
thread1 sell ticket : 33
thread1 sell ticket : 32
t1.join()  # 啓用join,下面將一直阻塞,直到T1運行結束
thread1 sell ticket : 31
thread1 sell ticket : 30
thread1 sell ticket : 29
thread1 sell ticket : 28
thread1 sell ticket : 27
thread1 sell ticket : 26
thread1 sell ticket : 25
thread1 sell ticket : 24
thread1 sell ticket : 23
thread1 sell ticket : 22
thread1 sell ticket : 21
thread1 sell ticket : 20
thread1 sell ticket : 19
thread1 sell ticket : 18
thread1 sell ticket : 17
thread1 sell ticket : 16
thread1 sell ticket : 15
thread1 sell ticket : 14
thread1 sell ticket : 13
thread1 sell ticket : 12
thread1 sell ticket : 11
thread1 sell ticket : 10
thread1 sell ticket : 9
thread1 sell ticket : 8
thread1 sell ticket : 7
thread1 sell ticket : 6
thread1 sell ticket : 5
thread1 sell ticket : 4
thread1 sell ticket : 3
thread1 sell ticket : 2
thread1 sell ticket : 1
>>> print('Y')
Y
>>> 

 

        3.2、Lock類。

        鎖有且只有兩種狀態:鎖定和未鎖定。獲得鎖函數用acquire()、 釋放鎖函數用release()。當多線程爭奪鎖時,允許第一個獲得鎖的線程進入臨界區,並執行代碼,其它後面到達的所有線程都將被阻塞,直到第一個獲得鎖的那個線程執行結束,退出臨界區,並釋放鎖後,其它等待的線程纔可以獲得鎖並進入臨界區。注意,那些被阻塞的線程是沒有順序的,並不是先到先得,而是不確定的。

未加鎖:

>>> import threading
>>> import time
>>> 
>>> tickets = 50
>>> def thread1():
	global tickets  # 全局變量
	while tickets > 0:
		print("thread1 sell ticket : %d\r\n" % tickets)
		tickets -= 1
		time.sleep(0.1)
	return True

>>> def thread2():
	global tickets  # 全局變量
	while tickets > 0:
		print("thread2 sell ticket : %d\r\n" % tickets)
		tickets -= 1
		time.sleep(0.1)
	return True

>>> threads = []
>>> t1 = threading.Thread(target=thread1)
>>> threads.append(t1)
>>> t2 = threading.Thread(target=thread2)
>>> threads.append(t2)
>>> 
>>> for i, t in enumerate(threads):
	t.start()
	time.sleep(0.1)

	
thread1 sell ticket : 50


thread2 sell ticket : 49

thread1 sell ticket : 49



>>> thread2 sell ticket : 47

thread1 sell ticket : 47



thread2 sell ticket : 45

thread1 sell ticket : 45



thread2 sell ticket : 43

thread1 sell ticket : 43



thread2 sell ticket : 41

thread1 sell ticket : 41
......

加鎖:

>>> tickets = 20
>>> lock = threading.Lock()
>>> 
>>> def thread1():
	global tickets  # 全局變量
	while tickets > 0:
		lock.acquire()
		tickets -= 1
		print("thread1 sell ticket : %d\n" % tickets)
		lock.release()
		time.sleep(0.2)
	return True

>>> def thread2():
	global tickets  # 全局變量
	while tickets > 0:
		lock.acquire()
		tickets -= 1
		print("thread2 sell ticket : %d\n" % tickets)
		lock.release()
		time.sleep(0.2)
	return True

>>> threads = []
>>> t1 = threading.Thread(target=thread1)
>>> threads.append(t1)
>>> t2 = threading.Thread(target=thread2)
>>> threads.append(t2)
>>> 
>>> for i, t in enumerate(threads):
	t.start()

	
thread1 sell ticket : 19
>>> 
thread2 sell ticket : 18

thread1 sell ticket : 17

thread2 sell ticket : 16

thread1 sell ticket : 15

thread2 sell ticket : 14

thread1 sell ticket : 13

thread2 sell ticket : 12

thread1 sell ticket : 11

thread2 sell ticket : 10

thread1 sell ticket : 9

thread2 sell ticket : 8

thread1 sell ticket : 7

thread2 sell ticket : 6

thread1 sell ticket : 5

thread2 sell ticket : 4

thread1 sell ticket : 3

thread2 sell ticket : 2

thread1 sell ticket : 1

thread2 sell ticket : 0

        3.3、RLock類。

        RLock和Lock沒多大區別。RLock爲可重入鎖,可以由同一線程多次獲取。在內部,除了原始鎖使用的鎖定/解鎖狀態之外,它還使用“擁有線程”和“遞歸級別”的概念。在鎖定狀態下,某些線程擁有鎖; 在解鎖狀態下,沒有線程擁有它。申請和釋放必須成對出現:

>>> import threading
>>> rLock = threading.RLock()
>>> rLock.acquire()
True
>>> rLock.acquire()
True
>>> rLock.acquire()
True
>>> rLock.release()
>>> rLock.release()
>>> rLock.release()
>>> rLock.release()
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    rLock.release()
RuntimeError: cannot release un-acquired lock
>>> 
>>> # 說明RLock的acquire()與release()必須成對出現。
>>> lock.acquire()
True
>>> lock.acquire()



lock.release()
lock.release()
lock.release()
# 已經產生了死鎖,沒有反應了
lock.release()

        3.4、Condition類(更高級的鎖)

        

        線程的掛起與阻塞:

  掛起:是因爲我們需要進行調度然後認爲的暫停某個線程的執行,我們也會主動放下線程實現線程的繼續運行

  阻塞:多半是被動的,因爲資源訪問的競爭,或是線程衝突。

  阻塞的線程掛起放下後依然是阻塞的。

  可以把Condiftion理解爲一把高級的鎖,它提供了比Lock, RLock更高級的功能,允許我們能夠控制複雜的線程同步問題。

  threadiong.Condition在內部維護一個鎖對象(默認是RLock),可以在創建Condigtion對象的時候把鎖對象作爲參數傳入。

  condition方法:

  1.acquire():線程獲得鎖

  2.release():釋放鎖

  3.wait():wait方法釋放內部所佔用的瑣,同時線程被掛起,直至接收到通知被喚醒或超時(如果提供了timeout參數的話)。當線程被喚醒並重新佔有瑣的時候,程序纔會繼續執行下去。。

  4.notify():喚醒一個掛起的線程(如果存在掛起的線程)。注意:notify()方法不會釋放所佔用的瑣。

        5.notifyAll():喚醒所有掛起的線程(如果存在掛起的線程)。注意:這些方法不會釋放所佔用的瑣。

  捉迷藏:

>>> import threading, time
>>> 
>>> class Seeker(threading.Thread):
	def __init__(self, cond, name):
		threading.Thread.__init__(self)
		self.cond = cond
		self.name = name
	def run(self):
		time.sleep(1)  # 1.確保seeker晚於hider開始執行
		print('1\n')
		self.cond.acquire()  # 4. seeker申請鎖
		print ('我把眼睛蒙上了\n')
		self.cond.notify()  # 5.蒙上眼後通知hider,hider線程此時被喚醒並試圖獲取鎖,鎖將在seeker身上,所以hider會被阻塞,seeker繼續往下
		self.cond.wait()  # 6. seeker鎖被釋放並且掛起,hider就獲取鎖開始繼續往下運行了
		print('2\n')
		print ('我找到你了\n')
		self.cond.notify()  # 9.找到了之後通知hider,hider意圖獲取鎖但不行所以被阻塞,seeker往下
		self.cond.release()  # 10.seeker釋放鎖,以便被通知的hider可以或得到鎖
		print('3\n')
		print ('我贏了\n')

		
>>> 
>>> class Hider(threading.Thread):
	def __init__(self, cond, name):
		threading.Thread.__init__(self)
		self.cond = cond
		self.name = name
	def run(self):
		self.cond.acquire()  # 2.hider獲取鎖
		self.cond.wait()  # 3.hider被掛起然後釋放鎖
		print('4\n')
		print ('我已經藏好了\n')
		self.cond.notify()  # 7.藏好後通知seeker,seeker意圖獲取鎖,但是鎖在hider身上所以seeker被阻塞
		self.cond.wait()  # 8.hider被掛起,釋放鎖,seeker獲取鎖,seeker繼續往下運行
		print('5\n')
		self.cond.release()# 11. 在此句之前一點,seeker釋放了鎖(#10),hider得到鎖,隨即這句hider釋放鎖
		print ('被你找到了\n')

		
>>> 
>>> cond = threading.Condition()
>>> seeker = Seeker(cond, 'seeker')
>>> hider = Hider(cond, 'hider')
>>> threads = []
>>> threads.append(seeker)
>>> threads.append(hider)
>>> for i, t in enumerate(threads):
	t.start()

	
>>> 1

我把眼睛蒙上了

4

我已經藏好了

2

我找到你了

5
3


被你找到了
我贏了



>>> 

        3.5、Event類(利用標誌位實現的鎖)

        

        Event實現與Condition類似的功能,不過比Condition簡單一點。它通過維護內部的標識符來實現線程間的同步問題。

        1.Event.wait() : 堵塞線程,直到Event對象內部標識位被設爲True或超時(如果提供了參數timeout)。

        2.Event.clear() : 將標誌位置於false狀態。

        3.Event.set() : 設置標誌位爲true

        4.Event.isSet() : 判斷標誌位狀態

        用Event模擬紅綠燈: 

Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> 
>>> import threading
>>> import time
>>> 
>>> def light(event):
	print('線程阻塞中,啓動線程請輸入[true]')
	event.wait()  # 阻塞線程,直到Event對象內部的標誌位置爲True
	counts = 0
	while True:
		event.clear()
		print('the light is red')
		time.sleep(6)
		if counts < 5:
			event.set()
		else:
			event.wait()
			break
		print('the light is green')
		time.sleep(4)
		print('the light is yellow')
		time.sleep(2)
		counts += 1

		
>>> 
>>> def car(event):
	event.wait()  # 阻塞線程,直到Event對象內部的標誌位置爲True
	while True:
		if event.isSet():
			print('green or yellow is on ,let`s go!')
			time.sleep(2)
		else:
			print('red in on, we must stop!')
			time.sleep(2)

			
>>> 
>>> event = threading.Event()
>>> threads = []
>>> t1 = threading.Thread(target=light,args=(event,))
>>> threads.append(t1)
>>> t2 = threading.Thread(target=car,args=(event,))
>>> threads.append(t2)
>>> for i, t in enumerate(threads):
	t.start()

	
>>> 線程阻塞中,啓動線程請輸入[true]

>>> start = input
>>> start = input()
true
>>> start
'true'
>>> if start == 'true':
	event.set()

	
green or yellow is on ,let`s go!the light is red
>>> 

red in on, we must stop!
red in on, we must stop!
the light is greengreen or yellow is on ,let`s go!

green or yellow is on ,let`s go!
the light is yellowgreen or yellow is on ,let`s go!

the light is redred in on, we must stop!

red in on, we must stop!
red in on, we must stop!
the light is green
green or yellow is on ,let`s go!
green or yellow is on ,let`s go!
the light is yellow
green or yellow is on ,let`s go!
the light is red
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
the light is green
green or yellow is on ,let`s go!
green or yellow is on ,let`s go!
the light is yellow
green or yellow is on ,let`s go!
the light is red
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
the light is green
green or yellow is on ,let`s go!
green or yellow is on ,let`s go!
the light is yellow
green or yellow is on ,let`s go!
the light is red
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
the light is green
green or yellow is on ,let`s go!
green or yellow is on ,let`s go!
the light is yellow
green or yellow is on ,let`s go!
the light is red
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!

        3.6、Semaphore([value])類(信號量)

        values是一個內部計數,values默認是1,如果小於0,則會拋出 ValueError 異常,可以用於控制線程數併發數。

        信號量是最古老的同步原語之一。它是一個計數器,當資源消耗時遞減,當資源釋放時遞增。你可以認爲信號量代表它們的資源可用或不可用。信號量比鎖更加靈活,因爲可以有多個線程共用一個資源的一個實例。

        信號量實際上就相當於一個計算器:

        acquire([blocking]),計數器加1;
        release(),計數器減1;

        3.7、BoundedSemaphore([value])類(更安全的信號量)

        BoundedSemaphore同Semaphore,不同的是BoundedSemaphore計數器的值永遠不會超過它的初始值,它自動防止信號量釋放的次數多於獲得的次數,所以BoundedSemaphore更安全。

        信號量控制某個時間段內線程數量:

>>> import threading
>>> import time
>>> 
>>> MAX_COUNTS = 3
>>> nums = threading.BoundedSemaphore(MAX_COUNTS)
>>> 
>>> def count(n):
	print('\nacquire time: %s' % time.ctime())
	time.sleep(5)
	nums.release()
	print('\n%d release time: %s' % (n, time.ctime()))

	
>>> for i in range(MAX_COUNTS*2):
	nums.acquire()
	t=threading.Thread(target=count, args=(i,))
	t.start()
	print('\n%s start' % t.name)

	
True

acquire time: Sat Aug 24 23:09:04 2019
Thread-1 start

True

acquire time: Sat Aug 24 23:09:04 2019
Thread-2 start

True

Thread-3 start
acquire time: Sat Aug 24 23:09:04 2019


0 release time: Sat Aug 24 23:09:09 2019True
1 release time: Sat Aug 24 23:09:09 2019
2 release time: Sat Aug 24 23:09:09 2019




Thread-4 start
acquire time: Sat Aug 24 23:09:09 2019

True

Thread-5 start
acquire time: Sat Aug 24 23:09:09 2019

True

Thread-6 start
acquire time: Sat Aug 24 23:09:09 2019

>>> 
3 release time: Sat Aug 24 23:09:14 2019

4 release time: Sat Aug 24 23:09:14 2019

5 release time: Sat Aug 24 23:09:14 2019

        3.8、Timer類

        threading.Timer是threading.Thread的子類,可以在指定時間間隔後執行某個操作。通過調用start()方法,啓動計時器,就像使用線程一樣。通過調用cancel()方法可以停止計時器(在其動作開始之前,只有在計時器仍處於等待階段時纔有效。)。

>>> def fun1():
	print("%s I'm fun1" % time.ctime())

	
>>> def fun2():
	print("%s I'm fun2" % time.ctime())

	
>>> threads = []
>>> t1 = threading.Thread(target=fun1)
>>> threads.append(t1)
>>> t2 = threading.Timer(5, fun2)  # 5s後運行
>>> threads.append(t2)
>>> 
>>> for i, t in enumerate(threads):
	t.start()

	
Sat Aug 24 23:22:39 2019 I'm fun1
>>> 
Sat Aug 24 23:22:44 2019 I'm fun2

        3.9、Barrier類

        Barrier類是設置了一個線程數量障礙,當等待的線程到達了這個數量就會喚醒所有的等待線程,可用於併發初始化等場景。

 class Barrier(builtins.object)
 |  Barrier(parties, action=None, timeout=None)  parties障礙要求的線程數量,action是一個可調用的函數,timeout是wait方法未指定時超時的默認值。
 |  
 |  Implements a Barrier.實現了一個障礙。
 |  
 |  Useful for synchronizing a fixed number of threads at known synchronization
 |  points.  Threads block on 'wait()' and are simultaneously awoken once they
 |  have all made that call.用於在已知同步點同步固定數量的線程。線程阻塞在'wait()'上,並在所有線程都發出該調用後同時被喚醒。
 |  
 |  Methods defined here:
 |  
 |  __init__(self, parties, action=None, timeout=None)
 |      Create a barrier, initialised to 'parties' threads.
 |      
 |      'action' is a callable which, when supplied, will be called by one of
 |      the threads after they have all entered the barrier and just prior to
 |      releasing them all. If a 'timeout' is provided, it is used as the
 |      default for all subsequent 'wait()' calls.“action”是一個可調用的函數,當它被提供時,其中一個線程將在它們全部進入屏障並在釋放它們之前調用它。如果提供了“timeout”,它將作爲所有後續“wait()”調用的默認值。
 |  
 |  abort(self)
 |      Place the barrier into a 'broken' state.將障礙設置爲“破碎”狀態。
 |      
 |      Useful in case of error.  Any currently waiting threads and threads
 |      attempting to 'wait()' will have BrokenBarrierError raised.在出錯時有用。任何當前正在等待的線程和試圖“wait()”的線程都將引發breakbarriererror異常,直到reset方法來恢復障礙。
 |  
 |  reset(self)
 |      Reset the barrier to the initial state.將障礙重置爲初始狀態,重新開始攔截,相當於電腦的重啓按鍵。
 |      
 |      Any threads currently waiting will get the BrokenBarrier exception
 |      raised.當前等待的任何線程都將引發BrokenBarrierError異常。
 |  
 |  wait(self, timeout=None)
 |      Wait for the barrier.當前線程進入阻塞狀態。
 |      
 |      When the specified number of threads have started waiting, they are all
 |      simultaneously awoken. If an 'action' was provided for the barrier, one
 |      of the threads will have executed that callback prior to returning.
 |      Returns an individual index number from 0 to 'parties-1'.當開始等待的線程數量達到指定數量時,它們都被同時喚醒。如果爲障礙提供了一個“action”,其中一個線程將在返回之前執行該回調。
返回從0到“parties-1”的單個索引號。timeout:如果等待超時,則引發BrokenBarrierError異常。

 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
 |  
 |  broken
 |      Return True if the barrier is in a broken state.
 |  
 |  n_waiting
 |      Return the number of threads currently waiting at the barrier.返回當前等待的線程數
 |  
 |  parties
 |      Return the number of threads required to trip the barrier.返回通過障礙所需的線程數

>>> def fun(barrier:threading.Barrier, n:int):
	print("n_waiting%d--%s\n" % (barrier.n_waiting, time.ctime()))
	try:
		if n < 3:
			barrier.wait(1)  # 設置超時時間1s,然後引發BrokenBarrierError異常,異常被except立刻捕獲,後面的語句不會被執行
		else:
			if n == 5:
				barrier.reset()  # 重啓障礙
				print('******barrier had reset******')
			b = barrier.wait()
			print('after barrier %s\n' % b)
	except threading.BrokenBarrierError:
		print('Broken barrier in %s--%s\n' % (threading.current_thread(), time.ctime()))

		
>>> barrier = threading.Barrier(3)
>>> for i in range(1,15):
	threading.Event().wait(1)  # 延遲1s
	threading.Thread(target=fun,args=(barrier,i),name='Barrier%d' % i).start()

	
False
n_waiting0--Sun Aug 25 12:44:10 2019

False
Broken barrier in <Thread(Barrier1, started 6476)>--Sun Aug 25 12:44:12 2019
n_waiting0--Sun Aug 25 12:44:12 2019


Broken barrier in <Thread(Barrier2, started 2776)>--Sun Aug 25 12:44:12 2019

False
n_waiting0--Sun Aug 25 12:44:13 2019

Broken barrier in <Thread(Barrier3, started 6360)>--Sun Aug 25 12:44:13 2019

False
n_waiting0--Sun Aug 25 12:44:14 2019

Broken barrier in <Thread(Barrier4, started 996)>--Sun Aug 25 12:44:14 2019

False
n_waiting0--Sun Aug 25 12:44:15 2019

******barrier had reset******
False
n_waiting1--Sun Aug 25 12:44:16 2019

False
n_waiting2--Sun Aug 25 12:44:17 2019

after barrier 2
after barrier 0
after barrier 1



False
n_waiting0--Sun Aug 25 12:44:18 2019

False
n_waiting1--Sun Aug 25 12:44:19 2019

False
n_waiting2--Sun Aug 25 12:44:20 2019

after barrier 2
after barrier 0
after barrier 1



False
n_waiting0--Sun Aug 25 12:44:21 2019

False
n_waiting1--Sun Aug 25 12:44:22 2019

False
n_waiting2--Sun Aug 25 12:44:23 2019

after barrier 2
after barrier 1
after barrier 0



False
n_waiting0--Sun Aug 25 12:44:24 2019
>>> 

        四、Threading模塊的其它一些函數

        4.1、active_count() 

        返回當前活動的Thread對象個數,返回的個數中包含主線程。

>>> counts = threading.active_count()
>>> counts
3
>>> 

        4.2、enumerate()

        返回當前活動的Thread對象列表。

>>> threads = threading.enumerate()
>>> threads
[<_MainThread(MainThread, started 3208)>, <Thread(SockThread, started daemon 6436)>, <Thread(Barrier14, started 1420)>]
>>> 

        

        4.3、current_thread

        返回當前的Thread對象。

>>> thread = threading.current_thread
>>> thread
<function current_thread at 0x00000000028B6288>
>>> 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章