亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

python多線程用法實例詳解

系統 1518 0

本文實例分析了python多線程用法。分享給大家供大家參考。具體如下:

今天在學習嘗試學習python多線程的時候,突然發現自己一直對super的用法不是很清楚,所以先總結一些遇到的問題。當我嘗試編寫下面的代碼的時候:

復制代碼 代碼如下:
class A():
??? def __init__( self ):
??????? print "A"
class B( A ):
??? def __init__( self ):
??????? super( B, self ).__init__(? )
# A.__init__( self )
??????? print "B"
b = B()

出現:

super( B, self ).__init__()

TypeError: must be type, not classobj

最后發現原來是python中的新式類的問題,也就是A必須是新式類。解決方法如下兩種:

(1)

復制代碼 代碼如下:
class A( object ):
??? def __init__( self ):
??????? print "A"
class B( A ):
??? def __init__( self ):
??????? super( B, self ).__init__(? )
# A.__init__( self )?????? ##這條語句是舊式的,存在潛在的問題,應該避免使用
??????? print "B"
b = B()

(2)

復制代碼 代碼如下:
__metaclass__=type
class A():
??? def __init__( self ):
??????? print "A"
class B( A ):
??? def __init__( self ):
??????? super( B, self ).__init__(? )
# A.__init__( self )??? ##這條語句是舊式的,存在潛在的問題,應該避免使用
??????? print "B"
b = B()

注意 :如果在super( B, self ).__init__(? )

語句中添加self,也就是super( B, self ).__init__( self ),會出現如下的錯誤:

??? super( B, self ).__init__( self )

TypeError: __init__() takes exactly 1 argument (2 given)

以上只是一點點本人的心得筆記,呵呵。

復制代碼 代碼如下:
import threading, time
class myThread( threading.Thread ):
??? def __init__( self, threadname = "" ):
??????? #threading.Thread.__init__( self, name = threadname )
??????? super( myThread, self ).__init__( name = threadname )
??? def run( self ):
??????? print "starting====", self.name, time.ctime()
??????? time.sleep( 5 )
??????? print "end====", self.name, time.ctime(),
?
m = myThread( "m" )
n = myThread( "n" )
?
m.start()
n.start()

輸出的結果:

starting==== m Mon Aug 08 21:55:41 2011

starting==== n Mon Aug 08 21:55:41 2011

如果一個進程的主線程運行完畢而子線程還在執行的話,那么進程就不會退出,直到所有子線程結束為止。比如下面的例子:

復制代碼 代碼如下:
import threading, time
class myThread( threading.Thread ):
??? def __init__( self, threadname = "" ):
??????? #threading.Thread.__init__( self, name = threadname )
??????? super( myThread, self ).__init__( name = threadname )
??? def run( self ):
??????? print "starting====", self.name, time.ctime()
??????? time.sleep( 5 )
??????? print "end====", self.name, time.ctime(),
?
m = myThread( "m" )
m.start()
print "main end"
print

輸出的結果為:

starting==== m Mon Aug 08 22:01:06 2011

main end

end==== m Mon Aug 08 22:01:11 2011

也就是主進程結束之后,子進程還沒有結束

如果我們想在主進程結束的時候,子進程也結束的話,我們就應該使用setDaemon()函數。

實例如下:

復制代碼 代碼如下:
import threading, time
class myThread( threading.Thread ):
??? def __init__( self, threadname = "" ):
??????? #threading.Thread.__init__( self, name = threadname )
??????? super( myThread, self ).__init__( name = threadname )
??? def run( self ):
??????? print "starting====", self.name, time.ctime()
??????? time.sleep( 5 )
??????? print "end====", self.name, time.ctime(),
?
m = myThread( "m" )
m.setDaemon( True )
m.start()
print "main end"
print

輸出的結果為:starting====main end m Mon Aug 08 22:02:58 2011

可以看出,并沒有打印出子進程m結束的時候本應該打印的“end===…”

簡單的線程同步

個執行線程經常要共享數據,如果僅僅讀取共享數據還好,但是如果多個線程要修改共享數據的話就可能出現無法預料的結果。

假如兩個線程對象t1和t2都要對數值num=0進行增1運算,那么t1和t2都各對num修改10次的話,那么num最終的結果應該為20。但是如果當t1取得num的值時(假如此時num為0),系統把t1調度為“sleeping”狀態,而此時t2轉換為“running”狀態,此時t2獲得的num的值也為0,然后他把num+1的值1賦給num。系統又把t2轉化為“sleeping”狀態,t1為“running”狀態,由于t1已經得到num值為0,所以他也把num+1的值賦給了num為1。本來是2次增1運行,結果卻是num只增了1次。類似這樣的情況在多線程同時執行的時候是有可能發生的。所以為了防止這類情況的出現就要使用線程同步機制。

最簡單的同步機制就是“鎖”

鎖對象用threading.RLock類創建

復制代碼 代碼如下:
mylock = threading.RLock()

如何使用鎖來同步線程呢?線程可以使用鎖的acquire() (獲得)方法,這樣鎖就進入“locked”狀態。每次只有一個線程可以獲得鎖。如果當另一個線程試圖獲得這個鎖的時候,就會被系統變為“blocked”狀態,直到那個擁有鎖的線程調用鎖的release() (釋放)方法,這樣鎖就會進入“unlocked”狀態?!癰locked”狀態的線程就會收到一個通知,并有權利獲得鎖。如果多個線程處于“blocked”狀態,所有線程都會先解除“blocked”狀態,然后系統選擇一個線程來獲得鎖,其他的線程繼續沉默(“blocked”)。

復制代碼 代碼如下:
import threading
mylock = threading.RLock()
class mythread(threading.Thread)
??? ...
??? def run(self ...):
??????? ...???? #此處 不可以 放置修改共享數據的代碼
??????? mylock.acquire()
??????? ...???? #此處 可以 放置修改共享數據的代碼
??????? mylock.release()
??????? ...???? #此處 不可以 放置修改共享數據的代碼

我們把修改共享數據的代碼稱為“臨界區”,必須將所有“臨界區”都封閉在同一鎖對象的acquire()和release()方法調用之間。

鎖只能提供最基本的同步級別。有時需要更復雜的線程同步,例如只在發生某些事件時才訪問一個臨界區(例如當某個數值改變時)。這就要使用“條件變量”。

條件變量用threading.Condition類創建

復制代碼 代碼如下:
mycondition = threading.Condition()

條件變量是如何工作的呢?首先一個線程成功獲得一個條件變量后,調用此條件變量的wait()方法會導致這個線程釋放這個鎖,并進入“blocked”狀態,直到另一個線程調用同一個條件變量的notify()方法來喚醒那個進入“blocked”狀態的線程。如果調用這個條件變量的notifyAll()方法的話就會喚醒所有的在等待的線程。

如果程序或者線程永遠處于“blocked”狀態的話,就會發生死鎖。所以如果使用了鎖、條件變量等同步機制的話,一定要注意仔細檢查,防止死鎖情況的發生。對于可能產生異常的臨界區要使用異常處理機制中的finally子句來保證釋放鎖。等待一個條件變量的線程必須用notify()方法顯式的喚醒,否則就永遠沉默。保證每一個wait()方法調用都有一個相對應的notify()調用,當然也可以調用notifyAll()方法以防萬一。

同步隊列

我們經常會采用生產者/消費者關系的兩個線程來處理一個共享緩沖區的數據。例如一個生產者線程接受用戶數據放入一個共享緩沖區里,等待一個消費者線程對數據取出處理。但是如果緩沖區的太小而生產者和消費者兩個異步線程的速度不同時,容易出現一個線程等待另一個情況。為了盡可能的縮短共享資源并以相同速度工作的各線程的等待時間,我們可以使用一個“隊列”來提供額外的緩沖區。

創建一個“隊列”對象,可以使用如下代碼:

復制代碼 代碼如下:
import Queue
myqueue = Queue.Queue(maxsize = 10)

Queue.Queue類即是一個隊列的同步實現。隊列長度可為無限或者有限??赏ㄟ^Queue的構造函數的可選參數maxsize來設定隊列長度。如果maxsize小于1就表示隊列長度無限。

將一個值放入隊列中:

myqueue.put(10)

調用隊列對象的put()方法在隊尾插入一個項目。put()有兩個參數,第一個item為必需的,為插入項目的值;第二個block為可選參數,默認為1。如果隊列當前為空且block為1,put()方法就使調用線程暫停,直到空出一個數據單元。如果block為0,put方法將引發Full異常。

將一個值從隊列中取出:

myqueue.get()

調用隊列對象的get()方法從隊頭刪除并返回一個項目??蛇x參數為block,默認為1。如果隊列為空且block為1,get()就使調用線程暫停,直至有項目可用。如果block為0,隊列將引發Empty異常。

我們用一個例子來展示如何使用Queue:

復制代碼 代碼如下:
# queue_example.py
from Queue import Queue
import threading
import random
import time
?
# Producer thread
class Producer( threading.Thread ):
??? def __init__( self, threadname, queue ):
??????? threading.Thread.__init__( self, name = threadname )
??????? self.sharedata = queue
??? def run( self ):
??????? for i in range( 20 ):
??????????? print self.getName(), 'adding', i, 'to queue'
??????????? self.sharedata.put( i )
??????????? time.sleep( random.randrange( 10 ) / 10.0 )
??????????? print self.getName(), 'Finished'
?
# Consumer thread
class Consumer( threading.Thread ):
??? def __init__( self, threadname, queue ):
??????? threading.Thread.__init__( self, name = threadname )
??????? self.sharedata = queue
??? def run( self ):
??????? for i in range( 20 ):
??????????? print self.getName(), 'got a value:', self.sharedata.get()
??????????? time.sleep( random.randrange( 10 ) / 10.0 )
??????????? print self.getName(), 'Finished'
?
# Main thread
def main():
??? queue = Queue()
??? producer = Producer( 'Producer', queue )
??? consumer = Consumer( 'Consumer', queue )
?
??? print 'Starting threads ...'
??? producer.start()
??? consumer.start()
?
??? producer.join()
??? consumer.join()
?
??? print 'All threads have terminated.'
?
if __name__ == '__main__':
??? main()

程序輸出的結果為:

Starting threads ...

Producer adding 0 to queue

Consumer got a value: 0

Producer Finished

Producer adding 1 to queue

Producer Finished

Producer adding 2 to queue

Consumer Finished

Consumer got a value: 1

Consumer Finished

Consumer got a value: 2

Consumer Finished

Consumer got a value: Producer Finished

Producer adding 3 to queue

3

Consumer Finished

Consumer got a value: Producer Finished

Producer adding 4 to queue

4

ConsumerProducer Finished

?ConsumerFinished

got a value:Producer adding 5 to queue

5

Consumer Finished

Consumer got a value: Producer Finished

Producer adding 6 to queue

Producer Finished

Producer adding 7 to queue

6

Consumer Finished

Consumer got a value: 7

Producer Finished

Producer adding 8 to queue

Producer Finished

Producer adding 9 to queue

Consumer Finished

Consumer got a value: 8

ConsumerProducer? FinishedFinished

?

ConsumerProducer? got a value:adding 109

to queue

Producer Finished

Producer adding 11 to queue

Producer Finished

Producer adding 12 to queue

ConsumerProducer? FinishedFinished

?

ConsumerProducer? got a value:adding 1310

to queue

Producer Finished

Producer adding 14 to queue

Consumer Finished

Consumer got a value: 11

Producer Finished

Producer adding 15 to queue

Producer Finished

Producer adding 16 to queue

Producer Finished

Producer adding 17 to queue

Producer Finished

Producer adding 18 to queue

Consumer Finished

Consumer got a value: 12

Producer Finished

Producer adding 19 to queue

Producer Finished

Consumer Finished

Consumer got a value: 13

Consumer Finished

Consumer got a value: 14

Consumer Finished

Consumer got a value: 15

Consumer Finished

Consumer got a value: 16

Consumer Finished

Consumer got a value: 17

Consumer Finished

Consumer got a value: 18

Consumer Finished

Consumer got a value: 19

Consumer Finished

All threads have terminated.

希望本文所述對大家的Python程序設計有所幫助。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久国产麻豆 | 欧美成人伊人十综合色 | 99热精品在线观看 | 国产成人久久精品 | 久久99久久99精品免费看动漫 | 亚洲国产精品网站久久 | 波多野结衣一区二区 三区 波多野结衣一区二区三区 波多野结衣一区二区三区高清在线 | 四虎a| 豆国产96在线 | 亚洲 | 91色国产在线| 欧美与黑人午夜性猛交久久久 | 久久久国产精品免费看 | 伊人久久综合网站 | 成年女人视频免费观看一 | 亚洲一区有码 | 免费观看国产一区二区三区 | 欧美一区二区三区久久久人妖 | 色综合久久88中文字幕 | 福利视频91 | 99视频网 | 四虎影视在线永久免费观看 | 欧美另类性视频在线看 | 久久激情影院 | 中国国产成人精品久久 | 99热热久久这里只有精品166 | 2018一级毛片免费观看 | 99精品影视 | 欧美日本一区二区 | 亚洲成人一区 | 干一干操一操 | 成人在线精品视频 | 一级做受视频免费是看美女 | 亚洲精品日本一区二区在线 | 国产精品99久久久久久人 | 国产妇乱子伦视频免费 | 超清中文乱码字幕在线观看 | 精品亚洲无人区一区二区 | 亚洲成在人网站天堂一区二区 | 国产福利视频在线 | 波多野结衣精品中文字幕 | 再猛点深使劲爽日本免费视频 |