setDaemon方法必须在start方法前定义。t1.setDaemon(True),该语句的意思是:将主线程A设置为子线程t1的守护线程。也就是在执行程序时,t1会随着主线程A的退出而退出,不论t1是否执行完毕。
例1:当我们在程序中设置一个子线程并将其设为被守护线程时,那么该子线程会随着主线程的退出而退出,整个程序会在主线程执行结束后终止。
import threading import time def print_number(num): print("-----> %d" % num, time.ctime()) time.sleep(5) print("print_number ending......", time.ctime()) t1 = threading.Thread(target=print_number,args=(10,)) if __name__ == ‘__main__‘: t1.setDaemon(True) t1.start() print("Main thread ended...")
输出结果如下:
-----> 10 Wed Mar 20 10:54:21 2019 Main thread ended... ***Repl Closed***
可以看到,主线程结束后,子线程t1的最后一句并未被打印出来,因为它随着主线程的退出而退出。
例2:当我们设置了多个子线程时,将其中一个子线程t1设置为被守护线程,那么只有t1会随着主线程的退出而退出,其他子线程不会受到影响,依然会被执行完毕。此时就会出现一种很奇怪的情况,如下所示:
import threading import time def print_number(num): print("-----> %d" % num, time.ctime()) time.sleep(5) print("print_number ending......", time.ctime()) # 此处不应该被打印 def print_letter(letter): print("-----> %s" % letter, time.ctime()) time.sleep(10) print("print_letter ending......", time.ctime()) t1 = threading.Thread(target=print_number,args=(10,)) t2 = threading.Thread(target=print_letter,args=(‘hello‘,)) if __name__ == ‘__main__‘: t1.setDaemon(True) t1.start() t2.start() print("Main thread ended...")
在这段代码中,我们设置了两个子线程:t1和t2,并将t1设置为被守护线程。按照上述解释,t1应该在主线程结束时一并推出,所以t1的最后一句“print("print_number ending......", time.ctime())” 不会被运行。但是结果却不是这样:
-----> 10 Wed Mar 20 10:58:00 2019 -----> hello Wed Mar 20 10:58:00 2019 Main thread ended... print_number ending...... Wed Mar 20 10:58:05 2019 # t1线程的最后一行输出 print_letter ending...... Wed Mar 20 10:58:10 2019 ***Repl Closed***
可以看到,在主线程最后一句输出“Main thread ended...”之后,t1的最后一行代码也被打印了,并不如我们所期待的那样,最后一句不被打印。这是因为什么呢?
此时我们一共存在着3个线程:主线程、子线程t1 和 t2。t1是被守护的子线程,它的执行时间是5秒;t2不是被守护线程,它的执行时间是10秒。由于t2并不被守护,所以在主线程打印最后一句"Main thread ended..."后,t2依然在执行。这是需要注意的是,虽然主线程的代码执行完毕了,但是主线程并未退出。它依然在后台运行并等待t2执行结束。我们所说的守护线程,是随着主线程的退出而一并退出的。但是,如果依然有其他子线程在运行,主线程并不会马上退出,它会等待所有子线程结束后才会推出。所以,我们看到,主线程虽然执行完毕(但在后台并未退出),被守护的t1(时间较短)依然会继续执行后面的代码,因为子线程t2还在运行,所以主线程依然在后台挂起。当子线程t2(时间较长)执行完毕并退出后,主线程才会退出。
代码执行完毕 并不等于 线程的退出。即使主线程没有任何代码需要执行,主线程仍会在后台运行,并等待所有的子线程退出后才会退出。
例3: 如果我们想看到随着主线程退出而子线程退出的情况,那么就可以将t2设置为守护线程。
import threading import time def print_number(num): print("-----> %d" % num, time.ctime()) time.sleep(5) print("print_number ending......", time.ctime()) def print_letter(letter): print("-----> %s" % letter, time.ctime()) time.sleep(10) print("print_letter ending......", time.ctime()) t1 = threading.Thread(target=print_number,args=(10,)) t2 = threading.Thread(target=print_letter,args=(‘hello‘,)) if __name__ == ‘__main__‘: t2.setDaemon(True) # 将执行时间较长的t2设置为守护线程 t1.start() t2.start() print("Main thread ended...")
运行结果如下所示:
-----> 10 Wed Mar 20 11:24:59 2019 -----> hello Wed Mar 20 11:24:59 2019 Main thread ended... # 主线程执行完毕,并未退出,等待其他子线程(t1)执行 print_number ending...... Wed Mar 20 11:25:04 2019 # 线程t1执行完毕并退出 ***Repl Closed***
由于t1比t2的执行时间短,所以t1会先执行完毕并推出。而t2为被守护线程,所以它会随着主线程的退出而退出。在t1执行完毕并退出后,主线程不需要再等待其他子线程了,所以主线程就会退出,而t2会随着主线程一并退出,因此t2中的最后一行代码没有被执行。
join方法与setDaemon方法本质上是作用相反的两个方法:
1、join方法:t1.join--->是将t1的优先级提高,阻塞主线程,等待t1执行结束后再执行主线程以及其他子线程。
2、setDaemon方法:t1.setDaemon(True)--->是将t1捆绑到主线程上,它会随着主线程的退出而退出,并不考虑自己的代码是否执行完毕。所以对于t1来说,主线程的优先级更高。
原文地址:https://www.cnblogs.com/guyexiangyun/p/10563276.html