? ? ? ? 一、線程與進程的介紹參考之前寫的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
>>> t1.name
'Thread-4'
>>> t1.name = 'T1'
>>> t1
>>> 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 "
", line 1, in
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
--Sun Aug 25 12:44:12 2019
n_waiting0--Sun Aug 25 12:44:12 2019
Broken barrier in
--Sun Aug 25 12:44:12 2019
False
n_waiting0--Sun Aug 25 12:44:13 2019
Broken barrier in
--Sun Aug 25 12:44:13 2019
False
n_waiting0--Sun Aug 25 12:44:14 2019
Broken barrier in
--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)>,
,
]
>>>
? ? ? ??
? ? ? ? 4.3、current_thread
? ? ? ? 返回當前的Thread對象。
>>> thread = threading.current_thread
>>> thread
>>>
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
