激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - python多線程用法實(shí)例詳解

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

2020-05-19 09:13腳本之家 Python

這篇文章主要介紹了python多線程用法,以實(shí)例形式較為詳細(xì)的分析了線程同步、隊(duì)列等概念及用法技巧,需要的朋友可以參考下

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

今天在學(xué)習(xí)嘗試學(xué)習(xí)python多線程的時(shí)候,突然發(fā)現(xiàn)自己一直對super的用法不是很清楚,所以先總結(jié)一些遇到的問題。當(dāng)我嘗試編寫下面的代碼的時(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)原來是python中的新式類的問題,也就是A必須是新式類。解決方法如下兩種:

(1)

復(fù)制代碼 代碼如下:
class A( object ):
    def __init__( self ):
        print "A"
class B( A ):
    def __init__( self ):
        super( B, self ).__init__(  )
# A.__init__( self )       ##這條語句是舊式的,存在潛在的問題,應(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īng)該避免使用
        print "B"
b = B()


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

 

語句中添加self,也就是super( B, self ).__init__( self ),會出現(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)程的主線程運(yùn)行完畢而子線程還在執(zhí)行的話,那么進(jì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)程還沒有結(jié)束

如果我們想在主進(jìn)程結(jié)束的時(shí)候,子進(jìn)程也結(jié)束的話,我們就應(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

 

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

簡單的線程同步

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

假如兩個(gè)線程對象t1和t2都要對數(shù)值num=0進(jìn)行增1運(yùn)算,那么t1和t2都各對num修改10次的話,那么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。本來是2次增1運(yùn)行,結(jié)果卻是num只增了1次。類似這樣的情況在多線程同時(shí)執(zhí)行的時(shí)候是有可能發(fā)生的。所以為了防止這類情況的出現(xiàn)就要使用線程同步機(jī)制。

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

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

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

 

如何使用鎖來同步線程呢?線程可以使用鎖的acquire() (獲得)方法,這樣鎖就進(jìn)入“locked”狀態(tài)。每次只有一個(gè)線程可以獲得鎖。如果當(dāng)另一個(gè)線程試圖獲得這個(gè)鎖的時(shí)候,就會被系統(tǒng)變?yōu)?ldquo;blocked”狀態(tài),直到那個(gè)擁有鎖的線程調(diào)用鎖的release() (釋放)方法,這樣鎖就會進(jìn)入“unlocked”狀態(tài)。“blocked”狀態(tài)的線程就會收到一個(gè)通知,并有權(quán)利獲得鎖。如果多個(gè)線程處于“blocked”狀態(tài),所有線程都會先解除“blocked”狀態(tài),然后系統(tǒng)選擇一個(gè)線程來獲得鎖,其他的線程繼續(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ù)的代碼稱為“臨界區(qū)”,必須將所有“臨界區(qū)”都封閉在同一鎖對象的acquire()和release()方法調(diào)用之間。

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

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

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

 

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

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

同步隊(duì)列

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

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

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


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

 

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

myqueue.put(10)

調(diào)用隊(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)用線程暫停,直到空出一個(gè)數(shù)據(jù)單元。如果block為0,put方法將引發(fā)Full異常。

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

myqueue.get()

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

我們用一個(gè)例子來展示如何使用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.

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 伊人99re | 久久色网站 | 91九色精品国产 | 一级做a爱片毛片免费 | 黄色片免费看看 | av观看网站 | 精品成人av一区二区三区 | 看一级毛片| 一级免费在线视频 | 久久蜜桃香蕉精品一区二区三区 | 午色影院 | 一级电影在线观看 | 在线日韩 | 国产欧美日韩在线播放 | 国产麻豆交换夫妇 | 亚洲人成网站免费播放 | 国产精品免费久久久久 | 久久久久久久一区二区三区 | 国产亚洲精品网站 | av电影网在线观看 | 免费视频91 | 欧美精品免费一区二区三区 | 精品国产99久久久久久宅男i | 欧美综合成人 | 国产一级毛片视频在线! | 亚洲视频在线免费看 | 天天干免费视频 | 午夜男人在线观看 | 中国成人在线视频 | 欧美成人激情在线 | av手机在线免费播放 | 久草久视频| 九九热在线视频观看 | 孕妇体内谢精满日本电影 | 久久久久99999 | 成人午夜影院 | 黑人一级片视频 | 91av原创| 免费色片| 欧美日韩一区,二区,三区,久久精品 | 久久最新免费视频 |