Python線程threading模塊用法詳解
本文實(shí)例講述了Python線程threading模塊用法。分享給大家供大家參考,具體如下:
threading-更高級(jí)別的線程接口源代碼:Lib/threading.py 該模塊在較低級(jí)別thread模塊之上構(gòu)建更高級(jí)別的線程接口。另請(qǐng)參見(jiàn)mutex和Queue模塊。
該dummy_threading模塊適用于threading因thread缺失而無(wú)法使用的情況 。
注意: 從Python 2.6開(kāi)始,該模塊提供 符合 PEP 8的別名和屬性,以替換camelCase受Java的線程API啟發(fā)的名稱。此更新的API與multiprocessing模塊的API兼容 。但是,沒(méi)有為camelCase名稱的棄用設(shè)置計(jì)劃,它們?cè)赑ython 2.x和3.x中仍然完全受支持。
注意 :從Python 2.5開(kāi)始,幾個(gè)Thread方法引發(fā)RuntimeError 而不是AssertionError錯(cuò)誤地調(diào)用。
該模塊定義了以下功能和對(duì)象:
threading.active_count() threading.activeCount() 返回Thread當(dāng)前活動(dòng)的對(duì)象數(shù)。返回的計(jì)數(shù)等于返回的列表的長(zhǎng)度enumerate()。
在2.6版中更改:添加了active_count()拼寫(xiě)。
threading.Condition() 返回新條件變量對(duì)象的工廠函數(shù)。條件變量允許一個(gè)或多個(gè)線程等待,直到另一個(gè)線程通知它們。
請(qǐng)參閱條件對(duì)象。
threading.current_thread() threading.currentThread() 返回當(dāng)前Thread對(duì)象,對(duì)應(yīng)于調(diào)用者的控制線程。如果未通過(guò)threading模塊創(chuàng)建調(diào)用者的控制 線程,則返回具有有限功能的虛擬線程對(duì)象。
在2.6版中更改:添加了current_thread()拼寫(xiě)。
threading.enumerate() 返回Thread當(dāng)前活動(dòng)的所有對(duì)象的列表。該列表包括守護(hù)線程,由其創(chuàng)建的虛擬線程對(duì)象 current_thread()和主線程。它排除了尚未啟動(dòng)的已終止線程和線程。
threading.Event() 返回新事件對(duì)象的工廠函數(shù)。事件管理一個(gè)標(biāo)志,該標(biāo)志可以使用該set()方法設(shè)置為true,并使用該方法重置為false clear()。該wait()方法將阻塞,直到該標(biāo)志為真。
請(qǐng)參閱事件對(duì)象。
類threading.local 表示線程局部數(shù)據(jù)的類。線程局部數(shù)據(jù)是其值是線程特定的數(shù)據(jù)。要管理線程本地?cái)?shù)據(jù),只需創(chuàng)建一個(gè)local(或子類)實(shí)例并在其上存儲(chǔ)屬性:
mydata = threading.local()mydata.x = 1
對(duì)于單獨(dú)的線程,實(shí)例的值將不同。
有關(guān)更多詳細(xì)信息和大量示例,請(qǐng)參閱_threading_local模塊的文檔字符串 。
版本2.4中的新功能。
threading.Lock() 返回新原始鎖定對(duì)象的工廠函數(shù)。一旦線程獲得它,后續(xù)嘗試獲取它就會(huì)阻塞,直到它被釋放; 任何線程都可以釋放它。
請(qǐng)參見(jiàn)鎖定對(duì)象。
threading.RLock() 返回新的可重入鎖定對(duì)象的工廠函數(shù)。必須由獲取它的線程釋放重入鎖。一旦線程獲得了可重入鎖,同一個(gè)線程可以再次獲取它而不會(huì)阻塞; 線程必須在每次獲取它時(shí)釋放一次。
請(qǐng)參閱RLock對(duì)象。
threading.Semaphore([ 值] ) 返回新信號(hào)量對(duì)象的工廠函數(shù)。信號(hào)量管理一個(gè)計(jì)數(shù)器,表示release()呼叫數(shù)減去acquire()呼叫數(shù) 加上初始值。該acquire()方法在必要時(shí)阻止,直到它可以返回而不使計(jì)數(shù)器為負(fù)。如果沒(méi)有給出,則值默認(rèn)為1。
請(qǐng)參見(jiàn)信號(hào)量對(duì)象。
threading.BoundedSemaphore([ 值] ) 返回新的有界信號(hào)量對(duì)象的工廠函數(shù)。有界信號(hào)量檢查以確保其當(dāng)前值不超過(guò)其初始值。如果確實(shí)如此,ValueError則被提出。在大多數(shù)情況下,信號(hào)量用于保護(hù)容量有限的資源。如果信號(hào)量被釋放太多次,則表明存在錯(cuò)誤。如果沒(méi)有給出,則值默認(rèn)為1。
類 threading.Thread 表示控制線程的類。該類可以以有限的方式安全地進(jìn)行子類化。
請(qǐng)參見(jiàn)線程對(duì)象。
類 threading.Timer 在指定的時(shí)間間隔過(guò)后執(zhí)行函數(shù)的線程。
見(jiàn)Timer對(duì)象。
threading.settrace(func ) 為從threading模塊啟動(dòng)的所有線程設(shè)置跟蹤功能。在調(diào)用sys.settrace()其run()方法之前,將為每個(gè)線程 傳遞 func。
版本2.3中的新功能。
threading.setprofile(func ) 為從threading模塊啟動(dòng)的所有線程設(shè)置配置文件功能。在調(diào)用sys.setprofile()其run()方法之前,將為每個(gè)線程 傳遞 func。
版本2.3中的新功能。
threading.stack_size([ 大小] ) 返回創(chuàng)建新線程時(shí)使用的線程堆棧大小。可選的 size參數(shù)指定用于后續(xù)創(chuàng)建的線程的堆棧大小,并且必須為0(使用平臺(tái)或已配置的默認(rèn)值)或至少為32,768(32 KiB)的正整數(shù)值。如果未指定size,則使用0。如果不支持更改線程堆棧大小,ThreadError則引發(fā)a。如果指定的堆棧大小無(wú)效,則aValueError被提升,堆棧大小未經(jīng)修改。32kB是目前支持的最小堆棧大小值,以保證解釋器本身有足夠的堆棧空間。請(qǐng)注意,某些平臺(tái)可能對(duì)堆棧大小的值有特定限制,例如要求最小堆棧大小> 32kB或需要以系統(tǒng)內(nèi)存頁(yè)面大小的倍數(shù)進(jìn)行分配 - 應(yīng)提供平臺(tái)文檔以獲取更多信息(4kB頁(yè)面是常見(jiàn)的;在沒(méi)有更具體的信息的情況下,建議的方法是使用4096的倍數(shù)作為堆棧大小。可用性:Windows,具有POSIX線程的系統(tǒng)。
2.5版中的新功能。
異常threading.ThreadError 針對(duì)各種與線程相關(guān)的錯(cuò)誤提出,如下所述。請(qǐng)注意,許多接口使用RuntimeError而不是ThreadError。
下面記錄了對(duì)象的詳細(xì)界面。
該模塊的設(shè)計(jì)基于Java的線程模型。但是,在Java使鎖和條件變量成為每個(gè)對(duì)象的基本行為的地方,它們是Python中的獨(dú)立對(duì)象。Python的Thread類支持Java的Thread類的行為的子集; 目前,沒(méi)有優(yōu)先級(jí),沒(méi)有線程組,線程不能被銷(xiāo)毀,停止,暫停,恢復(fù)或中斷。Java的Thread類的靜態(tài)方法在實(shí)現(xiàn)時(shí)會(huì)映射到模塊級(jí)函數(shù)。
下面描述的所有方法都是原子執(zhí)行的。
線程對(duì)象此類表示在單獨(dú)的控制線程中運(yùn)行的活動(dòng)。有兩種方法可以指定活動(dòng):將可調(diào)用對(duì)象傳遞給構(gòu)造函數(shù),或者通過(guò)覆蓋run()子類中的方法。不應(yīng)在子類中重寫(xiě)其他方法(構(gòu)造函數(shù)除外)。換句話說(shuō), 只 覆蓋此類的init()和run()方法。
創(chuàng)建線程對(duì)象后,必須通過(guò)調(diào)用線程的start()方法啟動(dòng)其活動(dòng)。這將run()在單獨(dú)的控制線程中調(diào)用該方法。
一旦線程的活動(dòng)開(kāi)始,線程就被認(rèn)為是“活著的”。當(dāng)它的run()方法終止時(shí),它會(huì)停止活動(dòng)- 通常,或者通過(guò)引發(fā)未處理的異常。該is_alive()方法測(cè)試線程是否存活。
其他線程可以調(diào)用線程的join()方法。這會(huì)阻塞調(diào)用線程,直到調(diào)用其join()方法的線程終止。
線程有一個(gè)名字。名稱可以傳遞給構(gòu)造函數(shù),并通過(guò)name屬性讀取或更改。
線程可以標(biāo)記為“守護(hù)程序線程”。這個(gè)標(biāo)志的意義在于當(dāng)只剩下守護(hù)進(jìn)程線程時(shí)整個(gè)Python程序退出。初始值繼承自創(chuàng)建線程。可以通過(guò)daemon酒店設(shè)置標(biāo)志。
注意:守護(hù)程序線程在關(guān)閉時(shí)突然停止。他們的資源(例如打開(kāi)文件,數(shù)據(jù)庫(kù)事務(wù)等)可能無(wú)法正確發(fā)布。如果您希望線程正常停止,請(qǐng)使它們成為非守護(hù)進(jìn)程并使用合適的信令機(jī)制,例如Event。
有一個(gè)“主線程”對(duì)象; 這對(duì)應(yīng)于Python程序中的初始控制線程。它不是守護(hù)程序線程。
有可能創(chuàng)建“虛擬線程對(duì)象”。這些是與“外部線程”相對(duì)應(yīng)的線程對(duì)象,它們是在線程模塊外部啟動(dòng)的控制線程,例如直接來(lái)自C代碼。虛擬線程對(duì)象具有有限的功能; 他們總是被認(rèn)為是活著的和守護(hù)的,不能被join()編輯。它們永遠(yuǎn)不會(huì)被刪除,因?yàn)闊o(wú)法檢測(cè)外來(lái)線程的終止。
class threading.Thread(group = None,target = None,name = None,args =(),kwargs = {} ) 應(yīng)始終使用關(guān)鍵字參數(shù)調(diào)用此構(gòu)造函數(shù)。參數(shù)是:
小組應(yīng)該None; 在實(shí)現(xiàn)ThreadGroup類時(shí)為將來(lái)的擴(kuò)展保留 。
target是run()方法調(diào)用的可調(diào)用對(duì)象。默認(rèn)為None,意味著什么都沒(méi)有被調(diào)用。
name是線程名稱。默認(rèn)情況下,唯一名稱由“Thread- N ” 形式構(gòu)成,其中N是小十進(jìn)制數(shù)。
args是目標(biāo)調(diào)用的參數(shù)元組。默認(rèn)為()。
kwargs是目標(biāo)調(diào)用的關(guān)鍵字參數(shù)字典。默認(rèn)為{}。
如果子類重寫(xiě)構(gòu)造函數(shù),則必須確保Thread.init()在對(duì)線程執(zhí)行任何其他操作之前調(diào)用基類構(gòu)造函數(shù)()。 start() 開(kāi)始線程的活動(dòng)。
每個(gè)線程對(duì)象最多只能調(diào)用一次。它安排run()在單獨(dú)的控制線程中調(diào)用對(duì)象的方法。
此方法將RuntimeError在同一個(gè)線程對(duì)象上多次調(diào)用if。
run() 表示線程活動(dòng)的方法。
您可以在子類中重寫(xiě)此方法。標(biāo)準(zhǔn)run() 方法調(diào)用傳遞給對(duì)象構(gòu)造函數(shù)的可調(diào)用對(duì)象作為目標(biāo)參數(shù)(如果有),分別使用args和kwargs參數(shù)中的順序和關(guān)鍵字參數(shù)。
join([ 超時(shí)] ) 等到線程終止。這將阻塞調(diào)用線程,直到調(diào)用其join()方法的線程終止 - 正常或通過(guò)未處理的異常 - 或直到發(fā)生可選的超時(shí)。
當(dāng)超時(shí)參數(shù)存在而不存在時(shí)None,它應(yīng)該是一個(gè)浮點(diǎn)數(shù),指定操作的超時(shí)(以秒為單位)(或其中的分?jǐn)?shù))。由于join()總是返回None,必須調(diào)用isAlive()后join()決定超時(shí)是否發(fā)生了-如果線程還活著時(shí),join()調(diào)用超時(shí)。
當(dāng)timeout參數(shù)不存在時(shí)None,操作將阻塞,直到線程終止。
線程可以join()多次編輯。
join()提出了RuntimeError如果試圖加入當(dāng)前線程因?yàn)檫@將導(dǎo)致死鎖。join()在線程啟動(dòng)之前它也是一個(gè)錯(cuò)誤, 并且嘗試這樣做會(huì)引發(fā)相同的異常。
name 字符串僅用于識(shí)別目的。它沒(méi)有語(yǔ)義。多個(gè)線程可以賦予相同的名稱。初始名稱由構(gòu)造函數(shù)設(shè)置。
版本2.6中的新功能。
getName() setName() 適用于2.6之前的API name。
ident 此線程的“線程標(biāo)識(shí)符”或者None線程尚未啟動(dòng)。這是一個(gè)非零整數(shù)。看 thread.get_ident()功能。當(dāng)線程退出并創(chuàng)建另一個(gè)線程時(shí),可以回收線程標(biāo)識(shí)符。即使在線程退出后,該標(biāo)識(shí)符也可用。
版本2.6中的新功能。
is_alive() isAlive() 返回線程是否存活。
此方法True在run()方法啟動(dòng)之前返回,直到run()方法終止之后。模塊函數(shù) enumerate()返回所有活動(dòng)線程的列表。
在2.6版中更改:添加了is_alive()拼寫(xiě)。
daemon 一個(gè)布爾值,指示此線程是否為守護(hù)程序線程(True)或不是(False)。必須在start()調(diào)用之前設(shè)置,否則RuntimeError引發(fā)。它的初始值繼承自創(chuàng)建線程; 主線程不是守護(hù)程序線程,因此在主線程中創(chuàng)建的所有線程都默認(rèn)為daemon = False。
當(dāng)沒(méi)有剩下活著的非守護(hù)進(jìn)程線程時(shí),整個(gè)Python程序退出。
版本2.6中的新功能。
isDaemon() setDaemon() 適用于2.6之前的API daemon。
鎖定對(duì)象原始鎖是一種同步原語(yǔ),在鎖定時(shí)不屬于特定線程。在Python中,它是目前可用的最低級(jí)同步原語(yǔ),由thread 擴(kuò)展模塊直接實(shí)現(xiàn)。
原始鎖定處于“鎖定”或“解鎖”兩種狀態(tài)之一。它是在解鎖狀態(tài)下創(chuàng)建的。它有兩種基本方法,acquire()和 release()。當(dāng)狀態(tài)解鎖時(shí),acquire()將狀態(tài)更改為鎖定并立即返回。當(dāng)狀態(tài)被鎖定時(shí),acquire() 阻塞直到release()另一個(gè)線程中的調(diào)用將其更改為解鎖,然后該acquire()調(diào)用將其重置為已鎖定并返回。該 release()方法只應(yīng)在鎖定狀態(tài)下調(diào)用; 它將狀態(tài)更改為已解鎖并立即返回。如果嘗試釋放未鎖定的鎖,ThreadError則會(huì)引發(fā)a。
當(dāng)acquire()等待狀態(tài)轉(zhuǎn)為解鎖時(shí)阻塞多個(gè)線程時(shí),只有一個(gè)線程在release()呼叫重置狀態(tài)解鎖時(shí)繼續(xù); 哪個(gè)等待線程繼續(xù)進(jìn)行未定義,并且可能因?qū)崿F(xiàn)而異。
所有方法都以原子方式執(zhí)行。
Lock.acquire([ 阻止] ) 獲取鎖定,阻止或非阻止。
當(dāng)阻塞參數(shù)設(shè)置為T(mén)rue(默認(rèn)值)時(shí)調(diào)用,阻塞直到解鎖,然后將其設(shè)置為鎖定并返回True。
在使用阻塞參數(shù)設(shè)置為的情況下調(diào)用時(shí)False,請(qǐng)勿阻止。如果一個(gè)帶阻塞的調(diào)用設(shè)置為T(mén)rue阻塞,則False 立即返回; 否則,將鎖定設(shè)置為鎖定并返回True。
Lock.release() 解鎖。
鎖定鎖定后,將其重置為解鎖狀態(tài),然后返回。如果阻止任何其他線程等待鎖解鎖,則只允許其中一個(gè)繼續(xù)執(zhí)行。
在未鎖定的鎖上調(diào)用時(shí),ThreadError會(huì)引發(fā)a。
沒(méi)有回報(bào)價(jià)值。
RLock對(duì)象可重入鎖是同步原語(yǔ),可以由同一線程多次獲取。在內(nèi)部,除了原始鎖使用的鎖定/解鎖狀態(tài)之外,它還使用“擁有線程”和“遞歸級(jí)別”的概念。在鎖定狀態(tài)下,某些線程擁有鎖; 在解鎖狀態(tài)下,沒(méi)有線程擁有它。
要鎖定鎖,線程會(huì)調(diào)用其acquire()方法; 一旦線程擁有鎖,它就會(huì)返回。要解鎖鎖,線程會(huì)調(diào)用其 release()方法。acquire()/ release()call對(duì)可以嵌套; 只有最后一個(gè)release()(release()最外面的一對(duì))重置鎖才能解鎖并允許另一個(gè)被阻塞的線程 acquire()繼續(xù)進(jìn)行。
RLock.acquire([ blocking = 1 ] ) 獲取鎖定,阻止或非阻止。
在不帶參數(shù)的情況下調(diào)用:如果此線程已擁有鎖,則將遞歸級(jí)別遞增1,并立即返回。否則,如果另一個(gè)線程擁有該鎖,則阻塞直到鎖被解鎖。鎖解鎖后(不屬于任何線程),然后獲取所有權(quán),將遞歸級(jí)別設(shè)置為1,然后返回。如果多個(gè)線程被阻塞等待鎖解鎖,則一次只能有一個(gè)線程獲取鎖的所有權(quán)。在這種情況下沒(méi)有返回值。
在將blocking參數(shù)設(shè)置為true的情況下調(diào)用時(shí),執(zhí)行與不帶參數(shù)調(diào)用時(shí)相同的操作,并返回true。
在將blocking參數(shù)設(shè)置為false的情況下調(diào)用時(shí),請(qǐng)勿阻止。如果沒(méi)有參數(shù)的調(diào)用會(huì)阻塞,則立即返回false; 否則,執(zhí)行與不帶參數(shù)調(diào)用時(shí)相同的操作,并返回true。
RLock.release() 釋放鎖定,遞減遞歸級(jí)別。如果在遞減之后它為零,則將鎖重置為未鎖定(不由任何線程擁有),并且如果阻止任何其他線程等待鎖解鎖,則允許其中一個(gè)繼續(xù)進(jìn)行。如果在遞減之后遞歸級(jí)別仍然非零,則鎖保持鎖定并由調(diào)用線程擁有。
僅在調(diào)用線程擁有鎖時(shí)調(diào)用此方法。RuntimeError如果在鎖定解鎖時(shí)調(diào)用此方法,則引發(fā)A.
沒(méi)有回報(bào)價(jià)值。
條件對(duì)象條件變量總是與某種鎖相關(guān)聯(lián); 這可以傳入,或者默認(rèn)創(chuàng)建一個(gè)。(當(dāng)多個(gè)條件變量必須共享同一個(gè)鎖時(shí),傳入一個(gè)是有用的。)
條件變量具有acquire()與release()該調(diào)用相關(guān)聯(lián)的鎖的相應(yīng)方法的方法。它還有一種wait() 方法notify()和notifyAll()方法。只有在調(diào)用線程獲得鎖定時(shí)才調(diào)用這三個(gè),否則 RuntimeError引發(fā)a。
該wait()方法釋放鎖,然后阻塞,直到它被另一個(gè)線程中的相同條件變量喚醒notify()或notifyAll()調(diào)用。一旦被喚醒,它就會(huì)重新獲得鎖并返回。也可以指定超時(shí)。
該notify()方法喚醒等待條件變量的其中一個(gè)線程,如果有的話正在等待。該notifyAll()方法喚醒等待條件變量的所有線程。
注意:notify()和notifyAll()方法不釋放鎖; 這意味著被喚醒的一個(gè)或多個(gè)線程不會(huì)wait()立即從它們的調(diào)用返回,而是僅在調(diào)用notify()或notifyAll()最終放棄鎖的所有權(quán)的線程時(shí) 返回 。
提示:使用條件變量的典型編程風(fēng)格使用鎖來(lái)同步對(duì)某些共享狀態(tài)的訪問(wèn); 對(duì)狀態(tài)的特定變化感興趣的線程wait()重復(fù)調(diào)用,直到它們看到所需的狀態(tài),而線程修改狀態(tài)調(diào)用notify()或者 notifyAll()當(dāng)它們改變狀態(tài)時(shí)它可能是其中一個(gè)服務(wù)員的期望狀態(tài)。例如,以下代碼是具有無(wú)限緩沖區(qū)容量的通用生產(chǎn)者 - 消費(fèi)者情況:
# Consume one itemcv.acquire()while not an_item_is_available(): cv.wait()get_an_available_item()cv.release()# Produce one itemcv.acquire()make_an_item_available()cv.notify()cv.release()
要在notify()和之間進(jìn)行選擇notifyAll(),請(qǐng)考慮一個(gè)狀態(tài)更改是否只對(duì)一個(gè)或多個(gè)等待線程感興趣。例如,在典型的生產(chǎn)者 - 消費(fèi)者情況下,向緩沖區(qū)添加一個(gè)項(xiàng)目只需要喚醒一個(gè)消費(fèi)者線程。
class threading.Condition([ lock ] ) 如果給出了lock參數(shù)None,則它必須是一個(gè)Lock 或RLock對(duì)象,并且它被用作底層鎖。否則,將RLock創(chuàng)建一個(gè)新對(duì)象并將其用作基礎(chǔ)鎖。
acquire(* args ) 獲取底層鎖。此方法在底層鎖上調(diào)用相應(yīng)的方法; 返回值是該方法返回的任何值。
release() 釋放底層鎖。此方法在底層鎖上調(diào)用相應(yīng)的方法; 沒(méi)有回報(bào)價(jià)值。
wait([ 超時(shí)] ) 等到通知或直到發(fā)生超時(shí)。如果在調(diào)用此方法時(shí)調(diào)用線程尚未獲取鎖定,RuntimeError則引發(fā)a。
此方法釋放底層鎖,然后阻塞,直到它被另一個(gè)線程中的相同條件變量喚醒notify()或notifyAll()調(diào)用,或者直到發(fā)生可選超時(shí)。一旦被喚醒或超時(shí),它就會(huì)重新獲得鎖定并返回。
當(dāng)超時(shí)參數(shù)存在而不存在時(shí)None,它應(yīng)該是一個(gè)浮點(diǎn)數(shù),指定操作的超時(shí)(以秒為單位)(或其中的分?jǐn)?shù))。
當(dāng)?shù)讓渔i是a時(shí)RLock,它不會(huì)使用其release()方法釋放,因?yàn)楫?dāng)遞歸多次獲取鎖時(shí),這實(shí)際上可能無(wú)法解鎖。相反,使用了RLock類的內(nèi)部接口,即使多次遞歸獲取它也能真正解鎖它。然后,在重新獲取鎖時(shí),使用另一個(gè)內(nèi)部接口來(lái)恢復(fù)遞歸級(jí)別。
notify(n = 1 ) 默認(rèn)情況下,喚醒一個(gè)等待此條件的線程(如果有)。如果在調(diào)用此方法時(shí)調(diào)用線程尚未獲取鎖定, RuntimeError則引發(fā)a。
此方法最多喚醒等待條件變量的n個(gè)線程; 如果沒(méi)有線程在等待,那么這是一個(gè)無(wú)操作。
如果至少有n個(gè) 線程在等待,那么當(dāng)前的實(shí)現(xiàn)只會(huì)喚醒n 個(gè)線程。但是,依靠這種行為是不安全的。未來(lái)的優(yōu)化實(shí)現(xiàn)有時(shí)可能會(huì)喚醒超過(guò) n個(gè)線程。
注意:?jiǎn)拘丫€程實(shí)際上不會(huì)從其wait() 調(diào)用返回,直到它可以重新獲取鎖定。由于notify()不釋放鎖,其調(diào)用者應(yīng)該。
notify_all() notifyAll() 喚醒等待這種情況的所有線程。這種方法就像 notify(),但喚醒所有等待的線程而不是一個(gè)。如果在調(diào)用此方法時(shí)調(diào)用線程尚未獲取鎖定, RuntimeError則引發(fā)a。
在2.6版中更改:添加了notify_all()拼寫(xiě)。
信號(hào)量對(duì)象這是計(jì)算機(jī)科學(xué)史上最古老的同步原語(yǔ)之一,由早期的荷蘭計(jì)算機(jī)科學(xué)家Edsger W. Dijkstra(他使用P()而V()不是acquire()和release())發(fā)明。
信號(hào)量管理一個(gè)內(nèi)部計(jì)數(shù)器,該計(jì)數(shù)器按每次acquire()調(diào)用遞減并按每次 調(diào)用遞增release()。計(jì)數(shù)器永遠(yuǎn)不會(huì)低于零; 當(dāng)acquire()發(fā)現(xiàn)它為零時(shí),它會(huì)阻塞,等待其他線程調(diào)用release()。
class threading.Semaphore([ value ] ) 可選參數(shù)給出內(nèi)部計(jì)數(shù)器的初始值 ; 它默認(rèn)為1。如果給定的值小于0,ValueError則引發(fā)。
acquire([ 阻止] ) 獲取信號(hào)量。
在不帶參數(shù)的情況下調(diào)用:如果內(nèi)部計(jì)數(shù)器在輸入時(shí)大于零,則將其減1并立即返回。如果在進(jìn)入時(shí)為零,則阻塞,等待其他線程調(diào)用 release()以使其大于零。這是通過(guò)適當(dāng)?shù)幕ユi來(lái)完成的,這樣如果多個(gè)acquire()呼叫被阻止,它們 release()將完全喚醒其中一個(gè)。實(shí)現(xiàn)可以隨機(jī)選擇一個(gè),因此不應(yīng)該依賴被阻塞的線程被喚醒的順序。在這種情況下沒(méi)有返回值。
當(dāng)使用blocking設(shè)置為true 調(diào)用時(shí),執(zhí)行與不帶參數(shù)調(diào)用時(shí)相同的操作,并返回true。
當(dāng)阻塞設(shè)置為false 時(shí)調(diào)用,請(qǐng)勿阻止。如果沒(méi)有參數(shù)的調(diào)用會(huì)阻塞,則立即返回false; 否則,執(zhí)行與不帶參數(shù)調(diào)用時(shí)相同的操作,并返回true。
release() 釋放信號(hào)量,將內(nèi)部計(jì)數(shù)器遞增1。當(dāng)它在進(jìn)入時(shí)為零并且另一個(gè)線程正在等待它再次大于零時(shí),喚醒該線程。
Semaphore示例信號(hào)量通常用于保護(hù)容量有限的資源,例如數(shù)據(jù)庫(kù)服務(wù)器。在資源大小固定的任何情況下,您應(yīng)該使用有界信號(hào)量。在產(chǎn)生任何工作線程之前,您的主線程將初始化信號(hào)量:
maxconnections = 5...pool_sema = BoundedSemaphore(value=maxconnections)
一旦產(chǎn)生,工作線程在需要連接到服務(wù)器時(shí)調(diào)用信號(hào)量的獲取和釋放方法:
pool_sema.acquire()conn = connectdb()... use connection ...conn.close()pool_sema.release()
有界信號(hào)量的使用減少了導(dǎo)致信號(hào)量被釋放的編程錯(cuò)誤超過(guò)其獲取的編程錯(cuò)誤的可能性。
事件對(duì)象這是線程之間通信的最簡(jiǎn)單機(jī)制之一:一個(gè)線程發(fā)出事件信號(hào),其他線程等待它。
事件對(duì)象管理一個(gè)內(nèi)部標(biāo)志,該標(biāo)志可以使用該set()方法設(shè)置為true,并使用該 方法重置為false clear() 。該wait()方法將阻塞,直到該標(biāo)志為真。
類threading.Event 內(nèi)部標(biāo)志最初是假的。
is_set() isSet() 當(dāng)且僅當(dāng)內(nèi)部標(biāo)志為真時(shí)返回true。
在2.6版中更改:添加了is_set()拼寫(xiě)。
set() 將內(nèi)部標(biāo)志設(shè)置為true。等待它變?yōu)檎娴乃芯€程都被喚醒。wait()一旦標(biāo)志為真,調(diào)用的線程將不會(huì)阻塞。
clear() 將內(nèi)部標(biāo)志重置為false。隨后,線程調(diào)用 wait()將阻塞,直到set()被調(diào)用以再次將內(nèi)部標(biāo)志設(shè)置為true。
wait([ 超時(shí)] ) 阻止,直到內(nèi)部標(biāo)志為真。如果輸入時(shí)內(nèi)部標(biāo)志為真,則立即返回。否則,阻塞直到另一個(gè)線程調(diào)用 set()將標(biāo)志設(shè)置為true,或者直到發(fā)生可選的超時(shí)。
當(dāng)超時(shí)參數(shù)存在而不存在時(shí)None,它應(yīng)該是一個(gè)浮點(diǎn)數(shù),指定操作的超時(shí)(以秒為單位)(或其中的分?jǐn)?shù))。
此方法在退出時(shí)返回內(nèi)部標(biāo)志,因此它將始終返回, True除非給出超時(shí)并且操作超時(shí)。
在2.7版中更改:以前,該方法始終返回None。
定時(shí)器對(duì)象此類表示應(yīng)該在經(jīng)過(guò)一定時(shí)間后運(yùn)行的操作 - 計(jì)時(shí)器。 Timer是一個(gè)子類,Thread 因此也可以作為創(chuàng)建自定義線程的示例。
通過(guò)調(diào)用start() 方法,啟動(dòng)計(jì)時(shí)器,就像使用線程一樣。通過(guò)調(diào)用cancel()方法可以停止計(jì)時(shí)器(在其動(dòng)作開(kāi)始之前) 。計(jì)時(shí)器在執(zhí)行其操作之前將等待的時(shí)間間隔可能與用戶指定的時(shí)間間隔不完全相同。
例如:
def hello(): print 'hello, world't = Timer(30.0, hello)t.start() # after 30 seconds, 'hello, world' will be printed
class threading.Timer(interval,function,args = [],kwargs = {} ) 創(chuàng)建一個(gè)計(jì)時(shí)器,在經(jīng)過(guò)間隔秒后,將使用參數(shù)args和關(guān)鍵字參數(shù)kwargs運(yùn)行函數(shù)。
cancel() 停止計(jì)時(shí)器,取消執(zhí)行計(jì)時(shí)器的操作。這只有在計(jì)時(shí)器仍處于等待階段時(shí)才有效。
在with語(yǔ)句中使用鎖,條件和信號(hào)量此模塊提供的具有acquire()和 release()方法的所有對(duì)象都可以用作with 語(yǔ)句的上下文管理器。acquire()進(jìn)入塊時(shí)將調(diào)用該方法,并release()在退出塊時(shí)調(diào)用該方法。
目前Lock,RLock,Condition, Semaphore,和BoundedSemaphore對(duì)象可以用作 with聲明上下文管理。例如:
import threadingsome_rlock = threading.RLock()with some_rlock: print 'some_rlock is locked while this executes'在線程代碼中導(dǎo)入
雖然導(dǎo)入機(jī)制是線程安全的,但由于提供線程安全的方式存在固有限制,因此線程導(dǎo)入有兩個(gè)主要限制:
首先,除了在主模塊中,導(dǎo)入不應(yīng)該產(chǎn)生產(chǎn)生新線程然后以任何方式等待該線程的副作用。如果生成的線程直接或間接嘗試導(dǎo)入模塊,則不遵守此限制可能導(dǎo)致死鎖。 其次,所有導(dǎo)入嘗試必須在解釋器開(kāi)始關(guān)閉之前完成。僅通過(guò)從通過(guò)線程模塊創(chuàng)建的非守護(hù)程序線程執(zhí)行導(dǎo)入,可以最容易地實(shí)現(xiàn)這一點(diǎn)。直接使用線程模塊創(chuàng)建的守護(hù)程序線程和線程將需要一些其他形式的同步,以確保在系統(tǒng)關(guān)閉開(kāi)始后它們不會(huì)嘗試導(dǎo)入。不遵守此限制將導(dǎo)致在解釋器關(guān)閉期間出現(xiàn)間歇性異常和崩潰(因?yàn)楹笃趯?dǎo)入嘗試訪問(wèn)不再處于有效狀態(tài)的機(jī)器)。更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python進(jìn)程與線程操作技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門(mén)與進(jìn)階經(jīng)典教程》、《Python+MySQL數(shù)據(jù)庫(kù)程序設(shè)計(jì)入門(mén)教程》及《Python常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
相關(guān)文章:
1. java——Byte類/包裝類的使用說(shuō)明2. android studio實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器(無(wú)bug)3. python 讀txt文件,按‘,’分割每行數(shù)據(jù)操作4. python Selenium 庫(kù)的使用技巧5. android 控件同時(shí)監(jiān)聽(tīng)單擊和雙擊實(shí)例6. python+pywinauto+lackey實(shí)現(xiàn)PC端exe自動(dòng)化的示例代碼7. vue使用exif獲取圖片經(jīng)緯度的示例代碼8. python logging.info在終端沒(méi)輸出的解決9. 詳解android adb常見(jiàn)用法10. Python 忽略文件名編碼的方法
