python threading


python 提供很方便開thread的方式,其中有兩個function

  1. Thread.join() 等待thread結束
  2. Thread.setDaemon() 設為背景的thread
先來看看下面這一段程式碼


import threading
import time

class MyThread(threading.Thread):
    def __init__(self, init_counter_value):
        threading.Thread.__init__(self)
        #self.daemon = True
        self.counter = init_counter_value

    def run(self):
        while True:
            print self.counter
            self.count()
            time.sleep(1)

    def count(self):
        self.counter += 1

if __name__ == "__main__":
    t = MyThread(10)
    print t.isDaemon()
    t.start()
    #t.join()
    print "main finish"

這一段程式幾乎是使用 threading.Thread 的標準 pattern 了,我主線程去開了一個另外的線程,如果把這個線程透過 setDaemon() 來設成背景線程的話,則只要主線程不等待子線程的結果 join() 則程式會直接印出 main finish 而結束,因為設為背景線程會隨著主線程結束而結束,因此在線程中開無窮迴圈是可以結束的,只是結束的狀態是沒辦法定義的。

在 python 文件中提到 The entire Python program exits when no alive non-daemon threads are left. 意思為這個行程 Process 只要沒有活著的線程(這個線程不是背景線程)就會結束,否則控制權會交到開出來的子線程上,主線程已結束,因此透過 Ctrl+C 會沒辦法送 interrupt 進去子線程中,因此在寫 threading 程式的時候建議都設為背景線程以確保當主線程結束後子線程會結束。

另外 join() 主要是等待開出的線程結束,如果等待的是一個無窮回圈的線程則主線程呼叫 join() 會無法返回,不過join()可以帶timeout參數,看是要等待多久,如果過久沒有反應就不理子線程而向下執行。通常如果確定子線程是無窮回圈的話都會不設定透過 join() 來等待結束。而主線程和子線程可以透過 Queue 來溝通非常的方便