设定线程(进程)的daemon标志,当daemon=True表示守护,当daemon=False表示非守护(默认)
1、进程守护
守护进程会在主进程代码执行结束后就终止
守护进程内无法再开启子进程,否则会抛出异常:`AssertionError:daemonic processes are not allowed to havechildren`
进程之间是互相独立的,主进程代码运行结束,守护进程随即终止。
1.1 测试代码:
from multiprocessing import Process import time def task_one(): print("111") time.sleep(1) # 设置task_one为守护进程后,进程无法再开启子进程,否则会抛出异常 # p = Process(target=time.sleep(),args=(3,)) # p.start() print("222") def task_two(): print("333") time.sleep(1) print("444") if __name__=="__main__": p1 = Process(target=task_one) p1.daemon=True p2 = Process(target=task_two) p1.start() p2.start() print(">>>main<<<")
运行结果:
分析:
(1)主进程程序启动执行到p1子进程时,由于子进程需要开辟内存空间,需要耗费时间,于是顺序执行p2子进程,这时也因为要开辟内存空间需要耗费时间,于是执行`print(">>>main<<<")`,所以首先打印出`>>>main<<<`,主进程执行完毕,这时因为主进程内还有子进程p2没有运行完,所以判定为主进程未结束(说明:在进程中,只有非守护子进程执行完毕,主线程才会判定结束,此时p1为守护进程,p2为非守护进程)。
(2)按照顺序,p1子进程(p1是守护进程)开始执行,输出`111`,执行之后沉睡1秒,程序开始往下执行
(3)在p1子进程沉睡时,p2子进程(p2是非守护进程)开始执行,于是输出`333`,执行到`time.sleep(1)时陷入沉睡,,程序继续向下运行
(4)这时主进程已无内容执行,于是主进程结束,此时等待程序退出(但是主进程要退出程序,必须要等待所非守护子进程结束,于是程序跳过p1子进程,执行完p2子程序剩下的内容,此时p2子进程结束,程序判定主进程结束)
1.2 加入join
from multiprocessing import Process import time def task_one(): print("111") time.sleep(1) # 设置task_one为守护进程后,进程无法再开启子进程,否则会抛出异常 # p = Process(target=time.sleep(),args=(3,)) # p.start() print("222") def task_two(): print("333") time.sleep(2) print("444") if __name__=="__main__": p1 = Process(target=task_one) p1.daemon=True p2 = Process(target=task_two) p1.start() p2.start() print(">>>main<<<") p1.join()
运行结果:
分析:
join在进程中,是起到阻塞的作用,子进程执行完毕,才执行主进程。
(1)程序执行到join时,起到阻塞作用,必须等待join的子进程结束,才会退出子进程。
2、线程守护(`from threading import Thread`)
无论是进程还是线程,都遵循:守护xx会等待主xx运行完毕后被销毁。
主线程的结束意味着进程的结束,进程整体的资源都将被回收(主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束),而进程必须保证非守护线程都运行完毕后(主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收))才能结束。
同时,因为由于主线程子线程通用一块内存,所以不存在不同线程创建各自空间,所以就先输出子线程的执行任务代码,输出如下
```
111
333
>>>main<<<
444
```
没有输出`222`的原因同进程分析一样。