日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

多線程編程

 sun317 2013-01-23
         Python代碼代碼的執(zhí)行由python虛擬機(jī)(也叫解釋器主循環(huán))來控制。Python在設(shè)計(jì)之初就考慮到要在主循環(huán)中,同時(shí)只有一個(gè)線程在執(zhí)行,就像單CPU的系統(tǒng)中運(yùn)行多個(gè)進(jìn)程那樣,內(nèi)存中可以存放多個(gè)程序,但任意時(shí)候,只有一個(gè)程序在CPU中運(yùn)行。同樣,雖然python解釋器可以“運(yùn)行”多個(gè)線程,但在任意時(shí)刻,只有一個(gè)線程在解釋器中運(yùn)行。

    對(duì)python虛擬機(jī)的訪問由全局解釋器鎖(GIL)來控制,這個(gè)GIL能保證同一時(shí)刻只有一個(gè)線程在運(yùn)行。在多線程環(huán)境中,python虛擬機(jī)按以下方式執(zhí)行:

   1 設(shè)置GIL

   2 切換到一個(gè)線程去運(yùn)行

   3 運(yùn)行:(a.指定數(shù)量的字節(jié)碼指令,或者b.線程主動(dòng)讓出控制(可以調(diào)用time.sleep()))

   4 把線程設(shè)置為睡眠狀態(tài)

   5 解鎖GIL

   6 重復(fù)以上所有步驟

   那么為什么要提出多線程呢?我們首先看一個(gè)單線程的例子。

 

from time import sleep,ctime

 

def loop0():

    print 'start loop 0 at:',ctime()

    sleep(4)

    print 'loop 0 done at:',ctime()

 

def loop1():

    print 'start loop 1 at:',ctime()

    sleep(2)

    print 'loop 1 done at:',ctime()

 

def main():

    print 'starting at:',ctime()

    loop0()

    loop1()

    print 'all DONE at:',ctime()

 

if __name__=='__main__':

    main()

 

運(yùn)行結(jié)果:

>>>

starting at: Mon Aug 31 10:27:23 2009

start loop 0 at: Mon Aug 31 10:27:23 2009

loop 0 done at: Mon Aug 31 10:27:27 2009

start loop 1 at: Mon Aug 31 10:27:27 2009

loop 1 done at: Mon Aug 31 10:27:29 2009

all DONE at: Mon Aug 31 10:27:29 2009

>>>

可以看到單線程中的兩個(gè)循環(huán), 只有一個(gè)循環(huán)結(jié)束后另一個(gè)才開始。  總共用了6秒多的時(shí)間。假設(shè)兩個(gè)loop中執(zhí)行的不是sleep,而是一個(gè)別的運(yùn)算的話,如果我們能讓這些運(yùn)算并行執(zhí)行的話,是不是可以減少總的運(yùn)行時(shí)間呢,這就是我們提出多線程的前提。


Python中的多線程模塊:thread,threading,Queue。

1  thread ,這個(gè)模塊一般不建議使用。下面我們直接把以上的例子改一下,演示一下。

from time import sleep,ctime

import thread

 

def loop0():

    print 'start loop 0 at:',ctime()

    sleep(4)

    print 'loop 0 done at:',ctime()

 

def loop1():

    print 'start loop 1 at:',ctime()

    sleep(2)

    print 'loop 1 done at:',ctime()

def main():

    print 'starting at:',ctime()

    thread.start_new_thread(loop0,())

    thread.start_new_thread(loop1,())

    sleep(6)

    print 'all DONE at:',ctime()

 

if __name__=='__main__':

    main()  

運(yùn)行結(jié)果:

>>>

starting at: Mon Aug 31 11:04:39 2009

start loop 0 at: Mon Aug 31 11:04:39 2009

start loop 1 at: Mon Aug 31 11:04:39 2009

loop 1 done at: Mon Aug 31 11:04:41 2009

loop 0 done at: Mon Aug 31 11:04:43 2009

all DONE at: Mon Aug 31 11:04:45 2009

>>> 

可以看到實(shí)際是運(yùn)行了4秒兩個(gè)loop就完成了。效率確實(shí)提高了。

 

2 threading模塊

   首先看一下threading模塊中的對(duì)象:

   Thread    :表示一個(gè)線程的執(zhí)行的對(duì)象

   Lock     :鎖原語對(duì)象

   RLock    :可重入鎖對(duì)象。使單線程可以再次獲得已經(jīng)獲得的鎖

   Condition  :條件變量對(duì)象能讓一個(gè)線程停下來,等待其他線程滿足了某個(gè)“條件”,如狀態(tài)的改變或值的改變

   Event     :通用的條件變量。多個(gè)線程可以等待某個(gè)事件發(fā)生,在事件發(fā)生后,所有的線程都被激活

  Semaphore  :為等待鎖的線程提供一個(gè)類似“等候室”的結(jié)構(gòu)

  BoundedSemaphore  :與semaphore類似,只是它不允許超過初始值

  Timer       :  與Thread類似,只是,它要等待一段時(shí)間后才開始運(yùn)行

 其中Thread類是你主要的運(yùn)行對(duì)象,它有很多函數(shù),用它你可以用多種方法來創(chuàng)建線程,常用的為以下三種。

 創(chuàng)建一個(gè)Thread的實(shí)例,傳給它一個(gè)函數(shù)

 創(chuàng)建一個(gè)Thread實(shí)例,傳給它一個(gè)可調(diào)用的類對(duì)象

 從Thread派生出一個(gè)子類,創(chuàng)建一個(gè)這個(gè)子類的實(shí)例

 

 Thread類的函數(shù)有:

       getName(self)  返回線程的名字

     |  isAlive(self)  布爾標(biāo)志,表示這個(gè)線程是否還在運(yùn)行中

     |  isDaemon(self)  返回線程的daemon標(biāo)志

     |  join(self, timeout=None) 程序掛起,直到線程結(jié)束,如果給出timeout,則最多阻塞timeout秒

     |  run(self)  定義線程的功能函數(shù)

     |  setDaemon(self, daemonic)  把線程的daemon標(biāo)志設(shè)為daemonic

     |  setName(self, name)  設(shè)置線程的名字

     |  start(self)   開始線程執(zhí)行

 

   下面看一個(gè)例子:(方法一:創(chuàng)建Thread實(shí)例,傳遞一個(gè)函數(shù)給它)
import threading

from time import sleep,ctime

loops=[4,2]

def loop(nloop,nsec):

       print 'start loop',nloop,'at:',ctime()

       sleep(nsec)

       print 'loop',nloop,'done at:',ctime()

def main():

       print 'starting at:',ctime()

       threads=[]

       nloops=range(len(loops))

       for i in nloops:

              t=threading.Thread(target=loop,args=(i,loops[i]))

              threads.append(t)

       for i in nloops:

              threads[i].start()

       for i in nloops:

              threads[i].join()         

       print 'all done at:',ctime()

if __name__=='__main__':

       main()

    可以看到第一個(gè)for循環(huán),我們創(chuàng)建了兩個(gè)線程,這里用到的是給Thread類傳遞了函數(shù),把兩個(gè)線程保存到threads列表中,第二個(gè)for循環(huán)是讓兩個(gè)線程開始執(zhí)行。然后再讓每個(gè)線程分別調(diào)用join函數(shù),使程序掛起,直至兩個(gè)線程結(jié)束。

 

另外的例子:(方法二:創(chuàng)建一個(gè)實(shí)例,傳遞一個(gè)可調(diào)用的類的對(duì)象)

import threading

from time import sleep,ctime

loops=[4,2]

class ThreadFunc(object):

       def __init__(self,func,args,name=''):

              self.name=name

              self.func=func

              self.args=args

       def __call__(self):

              self.res=self.func(*self.args)

def loop(nloop,nsec):

       print 'start loop',nloop,'at:',ctime()

       sleep(nsec)

       print 'loop',nloop,'done at:',ctime()

def main():

       print 'starting at:',ctime()

       threads=[]

       nloops=range(len(loops))

       for i in nloops:

              t=threading.Thread(target=ThreadFunc(loop,(i,loops[i]),loop.__name__))

              threads.append(t)

       for i in nloops:

              threads[i].start()

       for i in nloops:

              threads[i].join()

       print 'all done at:',ctime()

if __name__=='__main__':

       main()

 

最后的方法:(方法三:創(chuàng)建一個(gè)這個(gè)子類的實(shí)例)

import threading

from time import sleep,ctime

loops=(4,2)

class MyThread(threading.Thread):

       def __init__(self,func,args,name=''):

              threading.Thread.__init__(self)

              self.name=name

              self.func=func

              self.args=args

       def run(self):

              apply(self.func,self.args)

def loop(nloop,nsec):

       print 'start loop',nloop,'at:',ctime()

       sleep(nsec)

       print 'loop',nloop,'done at:',ctime()

      

def main():

       print 'starting at:',ctime()

       threads=[]

       nloops=range(len(loops))    

       for i in nloops:

              t=MyThread(loop,(i,loops[i]),loop.__name__)

              threads.append(t)

       for i in nloops:

              threads[i].start()     

       for i in nloops:

              threads[i].join()  

       print 'all done at:',ctime()

if __name__=='__main__':

       main()

另外我們可以把MyThread單獨(dú)編成一個(gè)腳本模塊,然后我們可以在別的程序里導(dǎo)入這個(gè)模塊直接使用。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約