1. 程式人生 > >Python多執行緒之執行緒建立和終止

Python多執行緒之執行緒建立和終止

python主要是通過thread和threading這兩個模組來實現多執行緒支援。python的thread模組是比較底層的模組,python的threading模組是對thread做了一些封裝,可以更加方便的被使用。但是python(cpython)由於GIL的存在無法使用threading充分利用CPU資源,如果想充分發揮多核CPU的計算能力需要使用multiprocessing模組(Windows下使用會有諸多問題)。

如果在對執行緒應用有較高的要求時可以考慮使用Stackless Python來完成。Stackless Python是Python的一個修改版本,對多執行緒程式設計有更好的支援,提供了對微執行緒的支援。微執行緒是輕量級的執行緒,在多個執行緒間切換所需的時間更多,佔用資源也更少。

通過threading模組建立新的執行緒有兩種方法:一種是通過threading.Thread(Target=executable Method)-即傳遞給Thread物件一個可執行方法(或物件);第二種是繼承threading.Thread定義子類並重寫run()方法。第二種方法中,唯一必須重寫的方法是run(),可根據需要決定是否重寫__init__()。值得注意的是,若要重寫__init__(),父類的__init__()必須要在函式第一行呼叫,否則會觸發錯誤“AssertionError: Thread.__init__() not called”

Python threading模組不同於其他語言之處在於它沒有提供執行緒的終止方法,通過Python threading.Thread()啟動的執行緒彼此是獨立的,若線上程A中啟動了執行緒B,那麼A、B是彼此獨立執行的執行緒。若想終止執行緒A的同時強力終止執行緒B,一個簡單的方法是通過線上程A中呼叫B.setDaemon(True)實現。但這樣帶來的問題是:執行緒B中的資源(開啟的檔案、資料傳輸等)可能會沒有正確的釋放。所以setDaemon()並非一個好方法,更為妥當的方式是通過Event機制。下面這段程式體現了setDaemon()和Event機制終止子執行緒的區別。

import threading  
import time  
class mythread(threading.Thread):   
    def __init__(self,stopevt = None,File=None,name = 'subthread',Type ='event'):   
        threading.Thread.__init__(self)   
        self.stopevt = stopevt   
        self.name = name   
        self.File = File   
        self.Type = Type   
           
                  
    def Eventrun(self):   
        while not self.stopevt.isSet():   
            print self.name +' alive\n'   
            time.sleep(2)   
        if self.File:   
            print 'close opened file in '+self.name+'\n'   
            self.File.close()   
        print self.name +' stoped\n'   
       
    def Daemonrun(self):   
        D = mythreadDaemon(self.File)   
        D.setDaemon(True)   
        while not self.stopevt.isSet():   
            print self.name +' alive\n'   
            time.sleep(2)   
        print self.name +' stoped\n'   
    def run(self):   
        if self.Type == 'event': self.Eventrun()   
        else: self.Daemonrun()   
class mythreadDaemon(threading.Thread):   
    def __init__(self,File=None,name = 'Daemonthread'):   
        threading.Thread.__init__(self)   
        self.name = name   
        self.File = File   
    def run(self):   
        while True:   
            print self.name +' alive\n'   
            time.sleep(2)   
        if self.File:   
            print 'close opened file in '+self.name+'\n'   
            self.File.close()   
        print self.name +' stoped\n'   
           
def evtstop():   
    stopevt = threading.Event()   
    FileA = open('testA.txt','w')   
    FileB = open('testB.txt','w')   
    A = mythread(stopevt,FileA,'subthreadA')   
    B = mythread(stopevt,FileB,'subthreadB')   
    print repr(threading.currentThread())+'alive\n'   
    print FileA.name + ' closed? '+repr(FileA.closed)+'\n'   
    print FileB.name + ' closed? '+repr(FileB.closed)+'\n'   
    A.start()   
    B.start()   
    time.sleep(1)   
    print repr(threading.currentThread())+'send stop signal\n'   
    stopevt.set()   
    A.join()   
    B.join()   
    print  repr(threading.currentThread())+'stoped\n'   
    print 'after A stoped, '+FileA.name + ' closed? '+repr(FileA.closed)+'\n'   
    print 'after A stoped, '+FileB.name + ' closed? '+repr(FileB.closed)+'\n'   
def daemonstop():   
    stopevt = threading.Event()   
    FileA = open('testA.txt','r')   
    A = mythread(stopevt,FileA,'subthreadA',Type = 'Daemon')   
    print repr(threading.currentThread())+'alive\n'   
    print FileA.name + ' closed? '+repr(FileA.closed)+'\n'   
    A.start()   
    time.sleep(1)   
    stopevt.set()   
    A.join()   
    print  repr(threading.currentThread())+'stoped\n'   
    print 'after A stoped, '+FileA.name + ' closed? '+repr(FileA.closed)+'\n'   
    if not FileA.closed:   
        print 'You see the differents, the resource in subthread may not released with setDaemon()'   
        FileA.close()   
if __name__ =='__main__':   
    print '-------stop subthread example with Event:----------\n'   
    evtstop()   
    print '-------Daemon stop subthread example :----------\n'   
    daemonstop()  

執行結果是:
-------stop subthread example with Event:----------   
<_MainThread(MainThread, started 2436)>alive   
testA.txt closed? False  
testB.txt closed? False  
subthreadA alive   
subthreadB alive   
  
<_MainThread(MainThread, started 2436)>send stop signal  
close opened file in subthreadA   
close opened file in subthreadB   
  
subthreadA stoped   
subthreadB stoped   
  
<_MainThread(MainThread, started 2436)>stoped   
after A stoped, testA.txt closed? True  
after A stoped, testB.txt closed? True  
-------Daemon stop subthread example :----------   
<_MainThread(MainThread, started 2436)>alive   
testA.txt closed? False  
subthreadA alive   
subthreadA stoped   
<_MainThread(MainThread, started 2436)>stoped   
after A stoped, testA.txt closed? False  
You see the differents, the resource in subthread may not released with setDaemon()