欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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)?!癰locked”狀態(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)目。可選參數(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)文章

  • 教你pycharm運(yùn)行Django第一個(gè)項(xiàng)目

    教你pycharm運(yùn)行Django第一個(gè)項(xiàng)目

    本文主要介紹了教你pycharm運(yùn)行Django第一個(gè)項(xiàng)目的實(shí)現(xiàn),文中通過(guò)圖文示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • Python下的Mysql模塊MySQLdb安裝詳解

    Python下的Mysql模塊MySQLdb安裝詳解

    在Python環(huán)境下,如果想操作MySQL數(shù)據(jù)庫(kù),難免會(huì)調(diào)用相應(yīng)的包,比如常用的:MySQLdb通過(guò)導(dǎo)入:import MySQLdb 后,可直接調(diào)用里面的方法
    2014-04-04
  • Python中py文件轉(zhuǎn)換成exe可執(zhí)行文件的方法

    Python中py文件轉(zhuǎn)換成exe可執(zhí)行文件的方法

    這篇文章主要介紹了Python中py文件轉(zhuǎn)換成exe可執(zhí)行文件的方法,需要的朋友可以參考下
    2019-06-06
  • 關(guān)于pandas.DataFrame的類(lèi)SQL操作

    關(guān)于pandas.DataFrame的類(lèi)SQL操作

    這篇文章主要介紹了關(guān)于pandas.DataFrame的類(lèi)SQL操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,
    2023-08-08
  • Python編程應(yīng)用設(shè)計(jì)原則詳解

    Python編程應(yīng)用設(shè)計(jì)原則詳解

    什么是好用的代碼呢?其實(shí)就是代碼質(zhì)量比較高,如何評(píng)價(jià)代碼質(zhì)量的高低呢?最常用的、最重要的評(píng)價(jià)標(biāo)準(zhǔn),就是代碼的可維護(hù)性、可讀性、可擴(kuò)展性、靈活性、簡(jiǎn)潔性、可復(fù)用性、可測(cè)試性
    2021-09-09
  • python實(shí)現(xiàn)批量轉(zhuǎn)換文件編碼(批轉(zhuǎn)換編碼示例)

    python實(shí)現(xiàn)批量轉(zhuǎn)換文件編碼(批轉(zhuǎn)換編碼示例)

    這篇文章主要介紹了python實(shí)現(xiàn)批量轉(zhuǎn)換文件編碼示例,指定文件編碼、目錄或擴(kuò)展名即可進(jìn)行轉(zhuǎn)換,大家參考使用吧
    2014-01-01
  • Python如何通過(guò)Flask-Mail發(fā)送電子郵件

    Python如何通過(guò)Flask-Mail發(fā)送電子郵件

    這篇文章主要介紹了Python如何通過(guò)Flask-Mail發(fā)送電子郵件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • pandas進(jìn)行數(shù)據(jù)的交集與并集方式的數(shù)據(jù)合并方法

    pandas進(jìn)行數(shù)據(jù)的交集與并集方式的數(shù)據(jù)合并方法

    今天小編就為大家分享一篇pandas進(jìn)行數(shù)據(jù)的交集與并集方式的數(shù)據(jù)合并方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • Python用list或dict字段模式讀取文件的方法

    Python用list或dict字段模式讀取文件的方法

    這篇文章主要給大家介紹了Python利用list字段模式或者dict字段模式讀取文件的方法,文中給出了詳細(xì)的介紹和示例代碼,相信對(duì)大家的理解和學(xué)習(xí)具有一定的參考借鑒價(jià)值,有需要的朋友可以跟著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-01-01
  • 對(duì)python append 與淺拷貝的實(shí)例講解

    對(duì)python append 與淺拷貝的實(shí)例講解

    今天小編就為大家分享一篇對(duì)python append 與淺拷貝的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05

最新評(píng)論