threading 多執行緒控制和處理
threading通過對thread模組進行二次封裝,提供了更方便的API來操作執行緒。
threading.Thread
Thread是threading模組中最重要的類之一,可以使用它來建立執行緒。有兩種方式來建立執行緒:一種是通過繼承Thread類,重寫它的run方法;另一種是建立一個threading.Thread物件,在它的初始化函式(__init__)中將可呼叫物件作為引數傳入。下面分別舉例說明。先來看看通過繼承 threading.Thread類來建立執行緒的例子:
####################################################
#coding=gbk
import threading, time, random
count = 0
class Counter(threading.Thread):
def __init__(self, lock, threadName):
''' 初始化物件。
@param lock: 瑣物件。
@param threadName: 執行緒名稱。
'''
super(Counter, self).__init__(name = threadName) # 注意:一定要顯式的呼叫父類的初始化函式。
self.lock = lock
def run(self):
'''重寫父類run方法,線上程啟動後執行該方法內的程式碼。
'''
global count
self.lock.acquire()
for i in xrange(10000):
count = count + 1
self.lock.release()
lock = threading.Lock()
for i in range(5):
Counter(lock, "thread-" + str(i)).start()
time.sleep(2) # 確保執行緒都執行完畢
print count
Thread是threading模組中最重要的類之一,可以使用它來建立執行緒。有兩種方式來建立執行緒:一種是通過繼承Thread類,重寫它的run方法;另一種是建立一個threading.Thread物件,在它的初始化函式(__init__)中將可呼叫物件作為引數傳入。下面分別舉例說明。先來看看通過繼承 threading.Thread類來建立執行緒的例子:
####################################################
#coding=gbk
import threading, time, random
count = 0
class Counter(threading.Thread):
def __init__(self, lock, threadName):
''' 初始化物件。
@param lock: 瑣物件。
@param threadName: 執行緒名稱。
'''
super(Counter, self).__init__(name = threadName) # 注意:一定要顯式的呼叫父類的初始化函式。
self.lock = lock
def run(self):
'''重寫父類run方法,線上程啟動後執行該方法內的程式碼。
'''
global count
self.lock.acquire()
for i in xrange(10000):
count = count + 1
self.lock.release()
lock = threading.Lock()
for i in range(5):
Counter(lock, "thread-" + str(i)).start()
time.sleep(2) # 確保執行緒都執行完畢
print count
在程式碼中,我們建立了一個Counter類,它繼承了threading.Thread。初始化函式接收兩個引數,一個是瑣物件,另一個是執行緒的名稱。在Counter中,重寫了從父類繼承的run方法,run方法將一個全域性變數逐一的增加10000。在接下來的程式碼中,建立了五個 Counter物件,分別呼叫其start方法。最後列印結果。這裡要說明一下run方法 和start方法: 它們都是從Thread繼承而來的,run()方法將線上程開啟後執行,可以把相關的邏輯寫到run方法中(通常把run方法稱為活動[Activity]。);start()方法用於啟動執行緒。
再看看另外一種建立執行緒的方法:
import threading, time, random
count = 0
lock = threading.Lock()
def doAdd():
'''將全域性變數count 逐一的增加10000。
'''
global count, lock
lock.acquire()
for i in xrange(10000):
count = count + 1
lock.release()
for i in range(5):
threading.Thread(target = doAdd, args = (), name = 'thread-' + str(i)).start()
time.sleep(2) # 確保執行緒都執行完畢
print count
count = 0
lock = threading.Lock()
def doAdd():
'''將全域性變數count 逐一的增加10000。
'''
global count, lock
lock.acquire()
for i in xrange(10000):
count = count + 1
lock.release()
for i in range(5):
threading.Thread(target = doAdd, args = (), name = 'thread-' + str(i)).start()
time.sleep(2) # 確保執行緒都執行完畢
print count
在這段程式碼中,我們定義了方法doAdd,它將全域性變數count 逐一的增加10000。然後建立了5個Thread物件,把函式物件doAdd 作為引數傳給它的初始化函式,再呼叫Thread物件的start方法,執行緒啟動後將執行doAdd函式。這裡有必要介紹一下 threading.Thread類的初始化函式原型:
def __init__(self, group=None, target=None, name=None, args=(), kwargs={})
引數group是預留的,用於將來擴充套件;
引數target是一個可呼叫物件(也稱為活動[activity]),線上程啟動後執行;
引數name是執行緒的名字。預設值為“Thread-N“,N是一個數字。
引數args和kwargs分別表示呼叫target時的引數列表和關鍵字引數。
def __init__(self, group=None, target=None, name=None, args=(), kwargs={})
引數group是預留的,用於將來擴充套件;
引數target是一個可呼叫物件(也稱為活動[activity]),線上程啟動後執行;
引數name是執行緒的名字。預設值為“Thread-N“,N是一個數字。
引數args和kwargs分別表示呼叫target時的引數列表和關鍵字引數。
Thread類還定義了以下常用方法與屬性:
Thread.getName()
Thread.setName()
Thread.name
用於獲取和設定執行緒的名稱。
Thread.getName()
Thread.setName()
Thread.name
用於獲取和設定執行緒的名稱。
Thread.ident
獲取執行緒的識別符號。執行緒識別符號是一個非零整數,只有在呼叫了start()方法之後該屬性才有效,否則它只返回None。
獲取執行緒的識別符號。執行緒識別符號是一個非零整數,只有在呼叫了start()方法之後該屬性才有效,否則它只返回None。
Thread.is_alive()
Thread.isAlive()
判斷執行緒是否是啟用的(alive)。從呼叫start()方法啟動執行緒,到run()方法執行完畢或遇到未處理異常而中斷 這段時間內,執行緒是啟用的。
Thread.isAlive()
判斷執行緒是否是啟用的(alive)。從呼叫start()方法啟動執行緒,到run()方法執行完畢或遇到未處理異常而中斷 這段時間內,執行緒是啟用的。
Thread.join([timeout])
呼叫Thread.join將會使主調執行緒堵塞,直到被呼叫執行緒執行結束或超時。引數timeout是一個數值型別,表示超時時間,如果未提供該引數,那麼主調執行緒將一直堵塞到被調執行緒結束。下面舉個例子說明join()的使用:
呼叫Thread.join將會使主調執行緒堵塞,直到被呼叫執行緒執行結束或超時。引數timeout是一個數值型別,表示超時時間,如果未提供該引數,那麼主調執行緒將一直堵塞到被調執行緒結束。下面舉個例子說明join()的使用:
import threading, time
def doWaiting():
print 'start waiting:', time.strftime('%H:%M:%S')
time.sleep(3)
print 'stop waiting', time.strftime('%H:%M:%S')
thread1 = threading.Thread(target = doWaiting)
thread1.start()
time.sleep(1) #確保執行緒thread1已經啟動
print 'start join'
thread1.join() #將一直堵塞,直到thread1執行結束。
print 'end join'
threading.RLock和threading.Lock
在threading模組中,定義兩種型別的瑣:threading.Lock和threading.RLock。它們之間有一點細微的區別,通過比較下面兩段程式碼來說明:
在threading模組中,定義兩種型別的瑣:threading.Lock和threading.RLock。它們之間有一點細微的區別,通過比較下面兩段程式碼來說明:
import threading
lock = threading.Lock() #Lock物件
lock.acquire()
lock.acquire() # 產生了死瑣。
lock.release()
lock.release()
lock = threading.Lock() #Lock物件
lock.acquire()
lock.acquire() # 產生了死瑣。
lock.release()
lock.release()
import threading
rLock = threading.RLock() #RLock物件
rLock.acquire()
rLock.acquire() #在同一執行緒內,程式不會堵塞。
rLock.release()
rLock.release()
rLock = threading.RLock() #RLock物件
rLock.acquire()
rLock.acquire() #在同一執行緒內,程式不會堵塞。
rLock.release()
rLock.release()
這兩種瑣的主要區別是:RLock允許在同一執行緒中被多次acquire。而Lock卻不允許這種情況。注意:如果使用RLock,那麼acquire和release必須成對出現,即呼叫了n次acquire,必須呼叫n次的release才能真正釋放所佔用的瑣。
threading.Condition
可以把Condiftion理解為一把高階的瑣,它提供了比Lock, RLock更高階的功能,允許我們能夠控制複雜的執行緒同步問題。threadiong.Condition在內部維護一個瑣物件(預設是RLock),可以在建立Condigtion物件的時候把瑣物件作為引數傳入。Condition也提供了acquire, release方法,其含義與瑣的acquire, release方法一致,其實它只是簡單的呼叫內部瑣物件的對應的方法而已。Condition還提供瞭如下方法(特別要注意:這些方法只有在佔用瑣 (acquire)之後才能呼叫,否則將會報RuntimeError異常。):
可以把Condiftion理解為一把高階的瑣,它提供了比Lock, RLock更高階的功能,允許我們能夠控制複雜的執行緒同步問題。threadiong.Condition在內部維護一個瑣物件(預設是RLock),可以在建立Condigtion物件的時候把瑣物件作為引數傳入。Condition也提供了acquire, release方法,其含義與瑣的acquire, release方法一致,其實它只是簡單的呼叫內部瑣物件的對應的方法而已。Condition還提供瞭如下方法(特別要注意:這些方法只有在佔用瑣 (acquire)之後才能呼叫,否則將會報RuntimeError異常。):
Condition.wait([timeout]):
wait方法釋放內部所佔用的瑣,同時執行緒被掛起,直至接收到通知被喚醒或超時(如果提供了timeout引數的話)。當執行緒被喚醒並重新佔有瑣的時候,程式才會繼續執行下去。
wait方法釋放內部所佔用的瑣,同時執行緒被掛起,直至接收到通知被喚醒或超時(如果提供了timeout引數的話)。當執行緒被喚醒並重新佔有瑣的時候,程式才會繼續執行下去。
Condition.notify():
喚醒一個掛起的執行緒(如果存在掛起的執行緒)。注意:notify()方法不會釋放所佔用的瑣。
喚醒一個掛起的執行緒(如果存在掛起的執行緒)。注意:notify()方法不會釋放所佔用的瑣。
Condition.notify_all()
Condition.notifyAll()
喚醒所有掛起的執行緒(如果存在掛起的執行緒)。注意:這些方法不會釋放所佔用的瑣。
Condition.notifyAll()
喚醒所有掛起的執行緒(如果存在掛起的執行緒)。注意:這些方法不會釋放所佔用的瑣。
現在寫個捉迷藏的遊戲來具體介紹threading.Condition的基本使用。假設這個遊戲由兩個人來玩,一個藏(Hider),一個找 (Seeker)。遊戲的規則如下:1. 遊戲開始之後,Seeker先把自己眼睛蒙上,蒙上眼睛後,就通知Hider;2. Hider接收通知後開始找地方將自己藏起來,藏好之後,再通知Seeker可以找了; 3. Seeker接收到通知之後,就開始找Hider。Hider和Seeker都是獨立的個體,在程式中用兩個獨立的執行緒來表示,在遊戲過程中,兩者之間的行為有一定的時序關係,我們通過Condition來控制這種時序關係。
#coding=utf-8
import threading, time
class Hider(threading.Thread):
def __init__(self, cond, name):
super(Hider, self).__init__()
self.cond = cond
self.name = name
def run(self):
time.sleep(1) # 確保先執行Seeker中的方法
self.cond.acquire()
print self.name + ': I have already closed my eyes'
self.cond.notify()
self.cond.wait()
print self.name + ': I found you ~_~'
self.cond.notify()
self.cond.release()
print self.name + ': You lose, I win'
class Seeker(threading.Thread):
def __init__(self, cond, name):
super(Seeker, self).__init__()
self.cond = cond
self.name = name
def run(self):
self.cond.acquire()
self.cond.wait() # 釋放對瑣的佔用,同時執行緒掛起在這裡,直到被notify並重新佔有瑣。
print self.name + ': I am ready, come and find me'
self.cond.notify()
self.cond.wait()
self.cond.release()
print self.name + ': You got it, ai~~~'
cond = threading.Condition()
seeker = Seeker(cond, 'seeker')
hider = Hider(cond, 'hider')
seeker.start()
hider.start()
import threading, time
class Hider(threading.Thread):
def __init__(self, cond, name):
super(Hider, self).__init__()
self.cond = cond
self.name = name
def run(self):
time.sleep(1) # 確保先執行Seeker中的方法
self.cond.acquire()
print self.name + ': I have already closed my eyes'
self.cond.notify()
self.cond.wait()
print self.name + ': I found you ~_~'
self.cond.notify()
self.cond.release()
print self.name + ': You lose, I win'
class Seeker(threading.Thread):
def __init__(self, cond, name):
super(Seeker, self).__init__()
self.cond = cond
self.name = name
def run(self):
self.cond.acquire()
self.cond.wait() # 釋放對瑣的佔用,同時執行緒掛起在這裡,直到被notify並重新佔有瑣。
print self.name + ': I am ready, come and find me'
self.cond.notify()
self.cond.wait()
self.cond.release()
print self.name + ': You got it, ai~~~'
cond = threading.Condition()
seeker = Seeker(cond, 'seeker')
hider = Hider(cond, 'hider')
seeker.start()
hider.start()
threading.Event
Event實現與Condition類似的功能,不過比Condition簡單一點。它通過維護內部的識別符號來實現執行緒間的同步問題。(threading.Event和.NET中的System.Threading.ManualResetEvent類實現同樣的功能。)
Event實現與Condition類似的功能,不過比Condition簡單一點。它通過維護內部的識別符號來實現執行緒間的同步問題。(threading.Event和.NET中的System.Threading.ManualResetEvent類實現同樣的功能。)
Event.wait([timeout])
堵塞執行緒,直到Event物件內部標識位被設為True或超時(如果提供了引數timeout)。
堵塞執行緒,直到Event物件內部標識位被設為True或超時(如果提供了引數timeout)。
Event.set()
將標識位設為Ture
將標識位設為Ture
Event.clear()
將標識伴設為False。
將標識伴設為False。
Event.isSet()
判斷標識位是否為Ture。
判斷標識位是否為Ture。
下面使用Event來實現捉迷藏的遊戲(可能用Event來實現不是很形象)
#coding=utf-8
#---- Event
#---- 捉迷藏的遊戲
import threading, time
class Hider(threading.Thread):
def __init__(self, cond, name):
super(Hider, self).__init__()
self.cond = cond
self.name = name
def run(self):
time.sleep(1) # 確保先執行Seeker中的方法
print self.name + ': I have already closed my eyes'
self.cond.set()
time.sleep(1)
self.cond.wait()
print self.name + ': I found you ~_~'
self.cond.set()
print self.name + ': You lose, I win'
class Seeker(threading.Thread):
def __init__(self, cond, name):
super(Seeker, self).__init__()
self.cond = cond
self.name = name
def run(self):
self.cond.wait()
print self.name + ': I am ready, come and find me'
self.cond.set()
time.sleep(1)
self.cond.wait()
print self.name + ': You got it, ai~~~'
cond = threading.Event()
seeker = Seeker(cond, 'seeker')
hider = Hider(cond, 'hider')
seeker.start()
hider.start()
#---- Event
#---- 捉迷藏的遊戲
import threading, time
class Hider(threading.Thread):
def __init__(self, cond, name):
super(Hider, self).__init__()
self.cond = cond
self.name = name
def run(self):
time.sleep(1) # 確保先執行Seeker中的方法
print self.name + ': I have already closed my eyes'
self.cond.set()
time.sleep(1)
self.cond.wait()
print self.name + ': I found you ~_~'
self.cond.set()
print self.name + ': You lose, I win'
class Seeker(threading.Thread):
def __init__(self, cond, name):
super(Seeker, self).__init__()
self.cond = cond
self.name = name
def run(self):
self.cond.wait()
print self.name + ': I am ready, come and find me'
self.cond.set()
time.sleep(1)
self.cond.wait()
print self.name + ': You got it, ai~~~'
cond = threading.Event()
seeker = Seeker(cond, 'seeker')
hider = Hider(cond, 'hider')
seeker.start()
hider.start()
threading.Timer
threading.Timer是threading.Thread的子類,可以在指定時間間隔後執行某個操作。下面是Python手冊上提供的一個例子:
threading.Timer是threading.Thread的子類,可以在指定時間間隔後執行某個操作。下面是Python手冊上提供的一個例子:
def hello():
print "hello, world"
t = Timer(3, hello)
t.start() # 3秒鐘之後執行hello函式。
print "hello, world"
t = Timer(3, hello)
t.start() # 3秒鐘之後執行hello函式。
threading模組中還有一些常用的方法沒有介紹:
threading.active_count()
threading.activeCount()
獲取當前活動的(alive)執行緒的個數。
threading.activeCount()
獲取當前活動的(alive)執行緒的個數。
threading.current_thread()
threading.currentThread()
獲取當前的執行緒物件(Thread object)。
threading.currentThread()
獲取當前的執行緒物件(Thread object)。
threading.enumerate()
獲取當前所有活動執行緒的列表。
獲取當前所有活動執行緒的列表。
threading.settrace(func)
設定一個跟蹤函式,用於在run()執行之前被呼叫。
設定一個跟蹤函式,用於在run()執行之前被呼叫。
threading.setprofile(func)
設定一個跟蹤函式,用於在run()執行完畢之後呼叫。
設定一個跟蹤函式,用於在run()執行完畢之後呼叫。
相關文章
- 【莫煩】Threading 多執行緒教程thread執行緒
- Python 之 threading(多執行緒)用法教程Pythonthread執行緒
- python之 threading(多執行緒)模組Pythonthread執行緒
- threading多執行緒資源加鎖thread執行緒
- python中的socket+threading多執行緒Pythonthread執行緒
- Python多執行緒之_thread與threading模組Python執行緒thread
- 前端多執行緒處理——async/await前端執行緒AI
- Spring多執行緒事務處理Spring執行緒
- 多工處理方式之二:多執行緒執行緒
- 多執行緒和多執行緒同步執行緒
- python threading 執行緒原理實驗Pythonthread執行緒
- Java多執行緒學習(2)執行緒控制Java執行緒
- 多執行緒理論執行緒
- 初學者看過來:Python中多執行緒和多處理的指南Python執行緒
- Java多執行緒並行處理任務的實現Java執行緒並行
- 執行緒安全處理之Threadlocal執行緒thread
- 如何處理執行緒死鎖執行緒
- mysql 5.7 執行緒阻塞處理MySql執行緒
- tomcat連線處理機制和執行緒模型Tomcat執行緒模型
- 多執行緒應用–Http請求阻塞回撥處理執行緒HTTP
- JAVA多執行緒下高併發的處理經驗Java執行緒
- 3種方式實現python多執行緒併發處理Python執行緒
- 多執行緒應用--Http請求阻塞回撥處理執行緒HTTP
- Spring Batch中透過多執行緒和非同步處理提高效能SpringBAT執行緒非同步
- 執行緒控制之休眠執行緒執行緒
- 多執行緒:執行緒池理解和使用總結執行緒
- 瀏覽器多執行緒和js單執行緒瀏覽器執行緒JS
- 執行緒與多執行緒執行緒
- 多執行緒【執行緒池】執行緒
- 多執行緒--執行緒管理執行緒
- 多執行緒:Operation和OperationQueue執行緒
- Netty中的執行緒處理EventLoopNetty執行緒OOP
- Spring如何處理執行緒併發Spring執行緒
- Java多執行緒之synchronized理論Java執行緒synchronized
- 畫江湖之 PHP 多執行緒開發 【利用多執行緒 序列任務變並行處理 從而減少序列執行時間】PHP執行緒並行
- Python的多程式和多執行緒Python執行緒
- 用 UI 多執行緒處理 WPF 大量渲染的解決方案UI執行緒
- ObjC 多執行緒簡析(一)-多執行緒簡述和執行緒鎖的基本應用OBJ執行緒
- JAVA多執行緒詳解(3)執行緒同步和鎖Java執行緒