2016/1/3 Python中的多線程(2):threading模塊

以前提了Python多線程的一點使用,今天介紹更好的threading模塊,它提供了Thread類和一些比較好用的同步機制。多線程

先介紹Thread類app

threading模塊中的Thread類有不少thread模塊裏沒有的方法,通常使用時能夠選擇幾種方法裏的一種:函數

  • 建立一個Thread實例,傳給它一個函數;
  • 建立一個Thread實例,傳給它一個可調用的類對象;
  • 從Thread派生一個子類,建立這個子類的實例。

能夠看看它有哪些方法oop

函數 描述
start() 開始線程的執行

run()spa

定義線程的功能的函數(通常會被子類重寫)
join(timeout=None) 程序掛起,知道線程結束,若是給了timeout,最多阻塞timeout秒

getName()線程

返回線程的名字
setName(name) 設置線程的名字
isAlive() 布爾標誌,表示這個線程是否還在運行中
isDaemon() 返回線程的daemon標誌
setDaemon(daemonic) 把線程的daemon標誌設置成daemonic

用threading模塊重寫咱們上次的例子:code

import threading
from time import sleep, ctime

loops = [4, 2]

def loop(nloop, nsec):
    print 'start loop%s at: %s\n' % (nloop, ctime()),
    sleep(nsec)
    print 'loop%s done at: %s\n' % (nloop, ctime()),

def main():
    print 'starting at: %s\n' % 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: %s\n' %ctime(),

if __name__ == '__main__':
    main()

結果也是以下顯示:對象

>>> 
starting at: Sun Jan 03 11:37:43 2016
start loop0 at: Sun Jan 03 11:37:43 2016
start loop1 at: Sun Jan 03 11:37:43 2016
loop1 done at: Sun Jan 03 11:37:45 2016
loop0 done at: Sun Jan 03 11:37:47 2016
all DONE at: Sun Jan 03 11:37:47 2016

 比起昨天的鎖,這裏只須要簡單地對每一個線程使用join()函數就能夠了。blog

join()看上去會比一個等待鎖釋放的無限循環清楚一些。它另外一個很重要的方面是能夠徹底不用調用,一旦線程啓動後就會一直執行,知道線程的函數結束退出位置。get

上面使用的是一種傳遞函數給Thread模塊,也能夠在建立線程的時候,傳一個可調用的類的實例來供線程啓動的時候執行,這是一種更面爲對象的方法。

代碼以下:

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 %s at: %s\n' %(nloop, ctime()),
    sleep(nsec)
    print 'loop %s done at: %s\n' %(nloop, 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()

結果和上面是同樣的,這裏就不貼了。

能夠看到咱們怎家了一個ThreadFunc類和建立Thread對象時實例化一個可調用類ThreadFunc的類對象。

建立線程時,Thread對象會調用咱們的ThreadFunc對象,會用到一個特殊函數__call__(),因爲咱們已經有了要用的參數,因此再也不傳到Thread()構造器中。

最後一種方法是從Thread類中派生一個子類,而後創造這個子類的實例。

import threading
from time import sleep, ctime

loops = [2, 4]

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%s at: %s' %(nloop, ctime())
    sleep(nsec)
    print 'loop%s done at:%s' %(nloop, ctime())

def main():
    print 'starting at:%s' % 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: %s' % ctime()

if __name__ == '__main__':
    main()
        
相關文章
相關標籤/搜索