最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python多線(xiàn)程用法實(shí)例詳解

 更新時(shí)間:2015年01月15日 09:26:23   投稿:shichen2014  
這篇文章主要介紹了python多線(xiàn)程用法,以實(shí)例形式較為詳細(xì)的分析了線(xiàn)程同步、隊(duì)列等概念及用法技巧,需要的朋友可以參考下

本文實(shí)例分析了python多線(xiàn)程用法。分享給大家供大家參考。具體如下:

今天在學(xué)習(xí)嘗試學(xué)習(xí)python多線(xiàn)程的時(shí)候,突然發(fā)現(xiàn)自己一直對(duì)super的用法不是很清楚,所以先總結(jié)一些遇到的問(wèn)題。當(dāng)我嘗試編寫(xiě)下面的代碼的時(shí)候:

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

出現(xiàn):

super( B, self ).__init__()

TypeError: must be type, not classobj

最后發(fā)現(xiàn)原來(lái)是python中的新式類(lèi)的問(wèn)題,也就是A必須是新式類(lèi)。解決方法如下兩種:

(1)

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

(2)

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

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

語(yǔ)句中添加self,也就是super( B, self ).__init__( self ),會(huì)出現(xiàn)如下的錯(cuò)誤:

    super( B, self ).__init__( self )

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

以上只是一點(diǎn)點(diǎn)本人的心得筆記,呵呵。

復(fù)制代碼 代碼如下:
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()

輸出的結(jié)果:

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

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

如果一個(gè)進(jìn)程的主線(xiàn)程運(yùn)行完畢而子線(xiàn)程還在執(zhí)行的話(huà),那么進(jìn)程就不會(huì)退出,直到所有子線(xiàn)程結(jié)束為止。比如下面的例子:

復(fù)制代碼 代碼如下:
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

輸出的結(jié)果為:

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

main end

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

也就是主進(jìn)程結(jié)束之后,子進(jìn)程還沒(méi)有結(jié)束

如果我們想在主進(jìn)程結(jié)束的時(shí)候,子進(jìn)程也結(jié)束的話(huà),我們就應(yīng)該使用setDaemon()函數(shù)。

實(shí)例如下:

復(fù)制代碼 代碼如下:
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

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

可以看出,并沒(méi)有打印出子進(jìn)程m結(jié)束的時(shí)候本應(yīng)該打印的“end===…”

簡(jiǎn)單的線(xiàn)程同步

個(gè)執(zhí)行線(xiàn)程經(jīng)常要共享數(shù)據(jù),如果僅僅讀取共享數(shù)據(jù)還好,但是如果多個(gè)線(xiàn)程要修改共享數(shù)據(jù)的話(huà)就可能出現(xiàn)無(wú)法預(yù)料的結(jié)果。

假如兩個(gè)線(xiàn)程對(duì)象t1和t2都要對(duì)數(shù)值num=0進(jìn)行增1運(yùn)算,那么t1和t2都各對(duì)num修改10次的話(huà),那么num最終的結(jié)果應(yīng)該為20。但是如果當(dāng)t1取得num的值時(shí)(假如此時(shí)num為0),系統(tǒng)把t1調(diào)度為“sleeping”狀態(tài),而此時(shí)t2轉(zhuǎn)換為“running”狀態(tài),此時(shí)t2獲得的num的值也為0,然后他把num+1的值1賦給num。系統(tǒng)又把t2轉(zhuǎn)化為“sleeping”狀態(tài),t1為“running”狀態(tài),由于t1已經(jīng)得到num值為0,所以他也把num+1的值賦給了num為1。本來(lái)是2次增1運(yùn)行,結(jié)果卻是num只增了1次。類(lèi)似這樣的情況在多線(xiàn)程同時(shí)執(zhí)行的時(shí)候是有可能發(fā)生的。所以為了防止這類(lèi)情況的出現(xiàn)就要使用線(xiàn)程同步機(jī)制。

最簡(jiǎn)單的同步機(jī)制就是“鎖”

鎖對(duì)象用threading.RLock類(lèi)創(chuàng)建

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

如何使用鎖來(lái)同步線(xiàn)程呢?線(xiàn)程可以使用鎖的acquire() (獲得)方法,這樣鎖就進(jìn)入“l(fā)ocked”狀態(tài)。每次只有一個(gè)線(xiàn)程可以獲得鎖。如果當(dāng)另一個(gè)線(xiàn)程試圖獲得這個(gè)鎖的時(shí)候,就會(huì)被系統(tǒng)變?yōu)椤癰locked”狀態(tài),直到那個(gè)擁有鎖的線(xiàn)程調(diào)用鎖的release() (釋放)方法,這樣鎖就會(huì)進(jìn)入“unlocked”狀態(tài)。“blocked”狀態(tài)的線(xiàn)程就會(huì)收到一個(gè)通知,并有權(quán)利獲得鎖。如果多個(gè)線(xiàn)程處于“blocked”狀態(tài),所有線(xiàn)程都會(huì)先解除“blocked”狀態(tài),然后系統(tǒng)選擇一個(gè)線(xiàn)程來(lái)獲得鎖,其他的線(xiàn)程繼續(xù)沉默(“blocked”)。

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

我們把修改共享數(shù)據(jù)的代碼稱(chēng)為“臨界區(qū)”,必須將所有“臨界區(qū)”都封閉在同一鎖對(duì)象的acquire()和release()方法調(diào)用之間。

鎖只能提供最基本的同步級(jí)別。有時(shí)需要更復(fù)雜的線(xiàn)程同步,例如只在發(fā)生某些事件時(shí)才訪(fǎng)問(wèn)一個(gè)臨界區(qū)(例如當(dāng)某個(gè)數(shù)值改變時(shí))。這就要使用“條件變量”。

條件變量用threading.Condition類(lèi)創(chuàng)建

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

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

如果程序或者線(xiàn)程永遠(yuǎn)處于“blocked”狀態(tài)的話(huà),就會(huì)發(fā)生死鎖。所以如果使用了鎖、條件變量等同步機(jī)制的話(huà),一定要注意仔細(xì)檢查,防止死鎖情況的發(fā)生。對(duì)于可能產(chǎn)生異常的臨界區(qū)要使用異常處理機(jī)制中的finally子句來(lái)保證釋放鎖。等待一個(gè)條件變量的線(xiàn)程必須用notify()方法顯式的喚醒,否則就永遠(yuǎn)沉默。保證每一個(gè)wait()方法調(diào)用都有一個(gè)相對(duì)應(yīng)的notify()調(diào)用,當(dāng)然也可以調(diào)用notifyAll()方法以防萬(wàn)一。

同步隊(duì)列

我們經(jīng)常會(huì)采用生產(chǎn)者/消費(fèi)者關(guān)系的兩個(gè)線(xiàn)程來(lái)處理一個(gè)共享緩沖區(qū)的數(shù)據(jù)。例如一個(gè)生產(chǎn)者線(xiàn)程接受用戶(hù)數(shù)據(jù)放入一個(gè)共享緩沖區(qū)里,等待一個(gè)消費(fèi)者線(xiàn)程對(duì)數(shù)據(jù)取出處理。但是如果緩沖區(qū)的太小而生產(chǎn)者和消費(fèi)者兩個(gè)異步線(xiàn)程的速度不同時(shí),容易出現(xiàn)一個(gè)線(xiàn)程等待另一個(gè)情況。為了盡可能的縮短共享資源并以相同速度工作的各線(xiàn)程的等待時(shí)間,我們可以使用一個(gè)“隊(duì)列”來(lái)提供額外的緩沖區(qū)。

創(chuàng)建一個(gè)“隊(duì)列”對(duì)象,可以使用如下代碼:

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

Queue.Queue類(lèi)即是一個(gè)隊(duì)列的同步實(shí)現(xiàn)。隊(duì)列長(zhǎng)度可為無(wú)限或者有限??赏ㄟ^(guò)Queue的構(gòu)造函數(shù)的可選參數(shù)maxsize來(lái)設(shè)定隊(duì)列長(zhǎng)度。如果maxsize小于1就表示隊(duì)列長(zhǎng)度無(wú)限。

將一個(gè)值放入隊(duì)列中:

myqueue.put(10)

調(diào)用隊(duì)列對(duì)象的put()方法在隊(duì)尾插入一個(gè)項(xiàng)目。put()有兩個(gè)參數(shù),第一個(gè)item為必需的,為插入項(xiàng)目的值;第二個(gè)block為可選參數(shù),默認(rèn)為1。如果隊(duì)列當(dāng)前為空且block為1,put()方法就使調(diào)用線(xiàn)程暫停,直到空出一個(gè)數(shù)據(jù)單元。如果block為0,put方法將引發(fā)Full異常。

將一個(gè)值從隊(duì)列中取出:

myqueue.get()

調(diào)用隊(duì)列對(duì)象的get()方法從隊(duì)頭刪除并返回一個(gè)項(xiàng)目??蛇x參數(shù)為block,默認(rèn)為1。如果隊(duì)列為空且block為1,get()就使調(diào)用線(xiàn)程暫停,直至有項(xiàng)目可用。如果block為0,隊(duì)列將引發(fā)Empty異常。

我們用一個(gè)例子來(lái)展示如何使用Queue:

復(fù)制代碼 代碼如下:
# 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()

程序輸出的結(jié)果為:

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.

希望本文所述對(duì)大家的Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • 簡(jiǎn)單談?wù)刾ython中的多進(jìn)程

    簡(jiǎn)單談?wù)刾ython中的多進(jìn)程

    multiprocessing模塊是python庫(kù)中最高級(jí)和功能最強(qiáng)大的模塊之一。本文就來(lái)給大家簡(jiǎn)單講講multiprocessing一般性技巧
    2016-11-11
  • python實(shí)現(xiàn)websocket的客戶(hù)端壓力測(cè)試

    python實(shí)現(xiàn)websocket的客戶(hù)端壓力測(cè)試

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)websocket的客戶(hù)端壓力測(cè)試,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • Python爬蟲(chóng)入門(mén)案例之爬取二手房源數(shù)據(jù)

    Python爬蟲(chóng)入門(mén)案例之爬取二手房源數(shù)據(jù)

    讀萬(wàn)卷書(shū)不如行萬(wàn)里路,學(xué)的扎不扎實(shí)要通過(guò)實(shí)戰(zhàn)才能看出來(lái),今天小編給大家?guī)?lái)一份python爬取二手房源信息的案例,可以用來(lái)直觀的了解房?jī)r(jià)行情,大家可以在過(guò)程中查缺補(bǔ)漏,看看自己掌握程度怎么樣
    2021-10-10
  • 基于Flask框架添加多個(gè)AI模型的API并進(jìn)行交互

    基于Flask框架添加多個(gè)AI模型的API并進(jìn)行交互

    這篇文章主要介紹了如何基于 Flask 框架開(kāi)發(fā) AI 模型 API 管理系統(tǒng),允許用戶(hù)添加、刪除不同 AI 模型的 API 密鑰,感興趣的可以了解下
    2025-03-03
  • 帶你精通Python正則表達(dá)式

    帶你精通Python正則表達(dá)式

    本文將給大家分享一份關(guān)于比較詳細(xì)的Python正則表達(dá)式寶典,學(xué)會(huì)之后你將對(duì)正則表達(dá)式達(dá)到精通的狀態(tài),一起來(lái)學(xué)習(xí)下面內(nèi)容吧
    2021-08-08
  • Python中pip工具的安裝以及使用

    Python中pip工具的安裝以及使用

    今天給大家?guī)?lái)關(guān)于Python的相關(guān)知識(shí),文章圍繞著pip工具的安裝以及使用展開(kāi),文中有非常詳細(xì)的圖文示例及介紹,需要的朋友可以參考下
    2021-06-06
  • django實(shí)現(xiàn)日志按日期分割

    django實(shí)現(xiàn)日志按日期分割

    這篇文章主要介紹了django實(shí)現(xiàn)日志按日期分割,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05
  • Pandas之缺失數(shù)據(jù)的實(shí)現(xiàn)

    Pandas之缺失數(shù)據(jù)的實(shí)現(xiàn)

    這篇文章主要介紹了Pandas之缺失數(shù)據(jù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 機(jī)器學(xué)習(xí)、深度學(xué)習(xí)和神經(jīng)網(wǎng)絡(luò)之間的區(qū)別和聯(lián)系

    機(jī)器學(xué)習(xí)、深度學(xué)習(xí)和神經(jīng)網(wǎng)絡(luò)之間的區(qū)別和聯(lián)系

    機(jī)器學(xué)習(xí)>神經(jīng)網(wǎng)絡(luò)>深度學(xué)習(xí)≈深度神經(jīng)網(wǎng)絡(luò),機(jī)器學(xué)習(xí)包括了神經(jīng)網(wǎng)絡(luò)在內(nèi)的許多算法,而神經(jīng)網(wǎng)絡(luò)又可以分為淺度神經(jīng)網(wǎng)絡(luò)和深度神經(jīng)網(wǎng)絡(luò),深度學(xué)習(xí)是使用了深度神經(jīng)網(wǎng)絡(luò)的技術(shù),雖然機(jī)器學(xué)習(xí)、深度學(xué)習(xí)和神經(jīng)網(wǎng)絡(luò)是不同的,但在構(gòu)建復(fù)雜系統(tǒng)時(shí),許多相關(guān)概念是混合在一起的
    2024-02-02
  • 使用Python中OpenCV和深度學(xué)習(xí)進(jìn)行全面嵌套邊緣檢測(cè)

    使用Python中OpenCV和深度學(xué)習(xí)進(jìn)行全面嵌套邊緣檢測(cè)

    這篇文章主要介紹了使用Python中OpenCV和深度學(xué)習(xí)進(jìn)行全面嵌套邊緣檢測(cè),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05

最新評(píng)論

江川县| 黎川县| 湘阴县| 洪洞县| 樟树市| 桃源县| 海南省| 台山市| 赣州市| 英吉沙县| 当涂县| 黎城县| 左云县| 若尔盖县| 望谟县| 宁南县| 汤阴县| 巴林右旗| 兴海县| 唐河县| 黑龙江省| 河东区| 哈巴河县| 桐庐县| 深泽县| 南城县| 庆阳市| 漠河县| 宜宾县| 磐石市| 永兴县| 澜沧| 汉阴县| 潜江市| 奉化市| 通渭县| 长子县| 阳春市| 苗栗市| 吉林市| 温州市|