Does Daemon Thread Exit with Main Thread?

主线程(进程)退出后,主线程创建的守护线程也会退出吗?

通过下面的代码测试:

Demo1: 进程创建普通线程

#!/usr/bin/python3
# FileName: daemonThread.py
# Author: lxw
# Date: 2016-02-25

import threading
import time

def show(num):
    time.sleep(3)
    print("In show(): {0}".format(num))
    with open("/home/lxw/Documents/NOTE", "w") as f:
        f.write("hello")

def main():
    th = threading.Thread(target=show, args=(1,))
    #th.setDaemon(True)
    th.start()
    print("main() over. Program exit!")


if __name__ == '__main__':
    main()
else:
    print("Being imported as a module.")

运行结果:

lxw Documents$ python3 daemonThread.py 
main() over. Program exit!
In show(): 1
lxw Documents$ 

"The entire Python program exits when no alive non-daemon threads are left".

只有当前进程的所有非守护线程 全部结束后,当前进程才能结束。

Demo2: 进程创建守护线程

#!/usr/bin/python3
# FileName: daemonThread.py
# Author: lxw
# Date: 2016-02-25

import threading
import time

def show(num):
    time.sleep(3)
    print("In show(): {0}".format(num))
    with open("/home/lxw/Documents/NOTE", "w") as f:
        f.write("hello")

def main():
    th = threading.Thread(target=show, args=(1,))
    th.setDaemon(True)
    th.start()
    print("main() over. Program exit!")


if __name__ == '__main__':
    main()
else:
    print("Being imported as a module.")

运行结果:

lxw Documents$ ls
daemonThread.py  NOTE  ThreadPool_Python
lxw Documents$ rm NOTE 
lxw Documents$ ls
daemonThread.py  ThreadPool_Python
lxw Documents$ python3 daemonThread.py 
main() over. Program exit!
lxw Documents$ ls
daemonThread.py  ThreadPool_Python

从运行结果我们可以看到,当前进程的守护线程 并没有结束,但当前进程仍然可以退出。并且当前进程结束后,该进程的守护线程也会结束,不会继续运行。

也就是说进程退出并不考虑守护线程,只考虑非守护线程。

 

通过这两段代码的验证,我们可以得出本文标题的答案:进程结束后,该进程的守护线程也会结束,不会继续运行。

 

Reference:

1. [Java基础] java的守护线程与非守护线程 虽然这篇文章讲的是Java的,但和Python也是通用的。
守护线程并非虚拟机内部可以提供,用户也可以自行的设定守护线程,方法:public final void setDaemon(boolean on) ;但是有几点需要注意:
1). thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个 IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。(备注:这点与守护进程有着明显的区别, 守护进程是创建后,让进程摆脱原会话的控制+让进程摆脱原进程组的控制+让进程摆脱原控制终端的控制;所以说寄托于虚拟机的语言机制跟系统级语言有着本质上面的区别)
2). 在Daemon线程中产生的新线程也是Daemon的。(这一点又是有着本质的区别了:守护进程fork()出来的子进程不再是守护进程,尽管它把父进程的进程相关信息复制过去了,但是子进程的进程的父进程不是init进程,所谓的守护进程本质上说就是“父进程挂掉,init收养,然后 文件0,1,2都是/dev/null,当前目录到/”)

2. 这篇博文的评论

posted @ 2016-02-25 00:28  XiaoweiLiu  阅读(652)  评论(0编辑  收藏  举报