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

python多線程用法實例詳解

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

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

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

復制代碼 代碼如下:
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)原來是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 ),會出現(xiàn)如下的錯誤:

    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()

輸出的結(jié)果:

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

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

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

復制代碼 代碼如下:
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

也就是主進程結(jié)束之后,子進程還沒有結(jié)束

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

實例如下:

復制代碼 代碼如下:
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結(jié)束的時候本應該打印的“end===…”

簡單的線程同步

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

假如兩個線程對象t1和t2都要對數(shù)值num=0進行增1運算,那么t1和t2都各對num修改10次的話,那么num最終的結(jié)果應該為20。但是如果當t1取得num的值時(假如此時num為0),系統(tǒng)把t1調(diào)度為“sleeping”狀態(tài),而此時t2轉(zhuǎn)換為“running”狀態(tài),此時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。本來是2次增1運行,結(jié)果卻是num只增了1次。類似這樣的情況在多線程同時執(zhí)行的時候是有可能發(fā)生的。所以為了防止這類情況的出現(xiàn)就要使用線程同步機制。

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

鎖對象用threading.RLock類創(chuàng)建

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

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

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

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

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

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

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

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

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

同步隊列

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

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

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

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

將一個值放入隊列中:

myqueue.put(10)

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

將一個值從隊列中取出:

myqueue.get()

調(diào)用隊列對象的get()方法從隊頭刪除并返回一個項目??蛇x參數(shù)為block,默認為1。如果隊列為空且block為1,get()就使調(diào)用線程暫停,直至有項目可用。如果block為0,隊列將引發(fā)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()

程序輸出的結(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.

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

相關(guān)文章

  • 簡單談談python中的多進程

    簡單談談python中的多進程

    multiprocessing模塊是python庫中最高級和功能最強大的模塊之一。本文就來給大家簡單講講multiprocessing一般性技巧
    2016-11-11
  • python實現(xiàn)websocket的客戶端壓力測試

    python實現(xiàn)websocket的客戶端壓力測試

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

    Python爬蟲入門案例之爬取二手房源數(shù)據(jù)

    讀萬卷書不如行萬里路,學的扎不扎實要通過實戰(zhàn)才能看出來,今天小編給大家?guī)硪环輕ython爬取二手房源信息的案例,可以用來直觀的了解房價行情,大家可以在過程中查缺補漏,看看自己掌握程度怎么樣
    2021-10-10
  • 基于Flask框架添加多個AI模型的API并進行交互

    基于Flask框架添加多個AI模型的API并進行交互

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

    帶你精通Python正則表達式

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

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

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

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

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

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

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

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

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

    使用Python中OpenCV和深度學習進行全面嵌套邊緣檢測

    這篇文章主要介紹了使用Python中OpenCV和深度學習進行全面嵌套邊緣檢測,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05

最新評論

和平县| 东乌珠穆沁旗| 都昌县| 嘉祥县| 信丰县| 内乡县| 普兰店市| 大港区| 治多县| 襄城县| 五莲县| 汨罗市| 五常市| 太仆寺旗| 丽江市| 华蓥市| 中江县| 佛山市| 大埔区| 宣化县| 黄陵县| 水城县| 普格县| 奈曼旗| 松桃| 枝江市| 团风县| 太仓市| 南澳县| 洛宁县| 宜川县| 孟村| 高雄市| 永安市| 界首市| 长岛县| 县级市| 商洛市| 大竹县| 巴中市| 康定县|