1. 程式人生 > >Python多執行緒中join函式與setDaemon函式使用說明

Python多執行緒中join函式與setDaemon函式使用說明

      在Python多執行緒程式設計的時候,經常需要用到join函式和setDaemon函式。之前對這兩個函式一直理解不是很到位。今天查閱了很多資料,對兩個函式的認識更加的深入一些了。

      join([timeout])可以參考Python文件說明。大概意思就是呼叫join函式會使得主調執行緒阻塞,直到被呼叫執行緒執行結束或超時。引數timeout是一個數值型別,用來表示超時時間,如果未提供該引數,那麼主調執行緒將一直阻塞直到被呼叫執行緒結束。

      借鑑一下別人的程式碼說明情況:

#!/usr/bin/env python
import threading
import time
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 print_func(num):
    while True:
        print "I am thread%d
" % num
        time.sleep(1)
threads = []
t1 = MyThread(print_func, (1, ), print_func.__name__)
threads.append(t1)
t2 = MyThread(print_func, (2, ), print_func.__name__)
threads.append(t2)
for t in threads:
    t.start()
    t.join()
print "ok\n"

      程式的執行輸出如下:

2

      檢視程式輸出發現只有第一個子執行緒在呼叫,第二個子執行緒以及父執行緒都沒有繼續走下去。這是因為join函式一直在等待子執行緒結束,但是迴圈使得子執行緒一直沒有結束,這樣後續子執行緒和主執行緒都阻塞了。使得只有第一個子執行緒在迴圈執行。

      改一下最後面的程式碼為:

for t in threads:
    t.start()
for t in threads:
    t.join()

      執行結果如下所示:

3

      可以看到執行緒一和執行緒二在交替執行。兩個子執行緒完成之前,父執行緒的print "ok\n"都不會執行。

      修改一下使得兩個子執行緒執行時間不一樣,會是怎樣的結果呢?

#!/usr/bin/env python
import threading
import time
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 print_func1(num):
    while True:
        print "I am thread%d" % num
        time.sleep(1)
def print_func2(num):
    while True:
        print "I am thread%d" % num
        time.sleep(2)
threads = []
t1 = MyThread(print_func1, (1, ), print_func1.__name__)
threads.append(t1)
t2 = MyThread(print_func2, (2, ), print_func2.__name__)
threads.append(t2)
for t in threads:
    t.start()
for t in threads:
    t.join()
print "ok\n"

      執行結果如下圖所示:

4 

      可以看到一個子執行緒的完成不會影響另外一個子執行緒,父執行緒仍然一直被阻塞,需要等待兩個子執行緒完成之後才會列印結果。

      setDaemon()可以參考Python文件說明。大概意思就是可以設定setDaemon的引數為True來表示將該執行緒指定為守護執行緒,如果引數為False就不指定執行緒為守護執行緒。設定setDaemon的引數為True之後。主執行緒和子執行緒會同時執行,主執行緒結束執行後,無論子執行緒執行與否,都會和主執行緒一起結束。

      借鑑一下別人的程式碼說明情況:

#!/usr/bin/env python
import threading
import time
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 print_func(num):
    while True:
        print "I am thread%d" % num
        time.sleep(1)
threads = []
t1 = MyThread(print_func, (1, ), print_func.__name__)
threads.append(t1)
t2 = MyThread(print_func, (2, ), print_func.__name__)
threads.append(t2)
for t in threads:
    t.setDaemon(True)
    t.start()
print "ok\n"

      執行結果如下圖所示:

1

      檢視程式輸出後可以發現print_func函式中的迴圈沒有繼續執行下去就退出了,由於setDaemon(True)把子執行緒設定為守護執行緒,子執行緒啟動後,父執行緒也繼續執行下去,當父執行緒執行完最後一條語句print "ok\n"後,沒有等待子執行緒是否完成,直接就退出了,同時子執行緒也一同結束。