day9-守护线程
前文概述
我们说在不加join的时候,主线程和子线程完全是并行的,没有了依赖关系,你主线程执行了,我子线程也执行了。但是加了join之后,主线程依赖子线程执行完毕后才往下走。现在我们要把所有的子线程变成我的守护进程。
前文拓展
查看当前线程类型和当前运行线程的个数
import threading, time def run(n): print("task:", n) time.sleep(2) print("task done", n, threading.current_thread()) # 查看每个线程的类型(主线程/子线程) start_time = time.time() for i in range(5): t = threading.Thread(target=run, args=("t-%s" %i,)) t.start() print("--------all thread has been finished", threading.current_thread(), threading.active_count()) # 查看线程类型和当前活动的线程个数 print("cost:", time.time() - start_time) #运行输出 task: t-0 task: t-1 task: t-2 task: t-3 task: t-4 --------all thead has finished <_MainThread(MainThread, started 4320621376)> 6 cost: 0.0007410049438476562 task done t-1 <Thread(Thread-2, started 123145371865088)> task done t-3 <Thread(Thread-4, started 123145382375424)> task done t-0 <Thread(Thread-1, started 123145366609920)> task done t-4 <Thread(Thread-5, started 123145387630592)> task done t-2 <Thread(Thread-3, started 123145377120256)>
解析:可以看出函数外执行的print()是主线程执行的,函数里面的是子线程执行的,同时可以看见一个有6个线程,5个子线程,1个主线程。
下面来学习新的知识,首先来了解下什么是守护进程?
守护进程:假设你是主人,你有几个仆人,这些个仆人都是为你服务的。可以帮你做很多事情,一个主人可以有多个守护进程,它们为你服务的前提是,主线程必须存在,如果主线程不存在,则守护进程也没了。那守护进程有什么作用呢?可以为你管理一些资源,打开一些文件,监听一些端口,它可以做很多事情,这些完全可以自定义。
守护线程
功能:只要主线程执行完毕,它不管子线程有没有执行完毕,主线程就退出了。所以也就是把所有的子线程变成守护线程,那么主程序(主线程)就不会等待子线程执行完毕后退出整个程序(主线程),转而主线程会等待非守护线程执行完毕才退出整个程序(主线程),所以主程序(主线程)就不会管这些结束/或没结束的守护线程了,不重要。
用法:使用setDaemon(True)设置守护线程,
前提:必须在启动线程前设置
import threading, time def run(n): print("task:", n) time.sleep(2) print("task done", n,threading.current_thread()) start_time = time.time() for i in range(5): t = threading.Thread(target=run, args=("t-%s" %i,)) # 把当前所有子线程设置为守护线程,一定要在start()之前设置 t.setDaemon(True) t.start() print("--------all thread has been finished",threading.current_thread(), threading.active_count()) print("cost:", time.time() - start_time) #运行输出 task: t-0 task: t-1 task: t-2 task: t-3 task: t-4 --------all thread has been finished <_MainThread(MainThread, started 1100)> 6 #5个子线程,1个主线程 cost: 0.0035004615783691406
解析:在设置了将所有子线程设置为守护线程后,代表这些子线程的执行结束与否不再影响主线程的执行过程。所以主程序(主线程)只会等待主线程的所有程序执行完毕后才会退出程序,而不会等待所有子线程的执行完毕与否。所以在主程序执行完毕后退出了,同时所有子线程的执行被强制中断了,因而没有继续执行和输出task done...。这就是我们只能看到每个线程启动后的输出。
在之前不加入join()时,主线程执行和子线程是并行执行的,虽然主线程不等待子线程执行完毕后再往下执行,但是由于程序最后隐含了join()的方法,所以在主线程(程序)执行结束之前,依然会等待所有子线程的执行完毕才退出整个程序。
应用场景
写一个socketServer,每一个客户端连接过来,socketServer都会为这个连接分配一个新的线程,在启动新的线程之后,此时如果手动停止socketServer,在这种情况下,因为主线程的服务停止了,它不会等待子线程的执行结束而结束程序运行。这样,在socketServer上设置子线程为守护线程。当socketServer主程序(主线程)停止后,整个程序就全部退出了。