场景一:手动创建线程:
import threading,time #threading 线程模块 def test(desc): for i in range(5): time.sleep(1) print(desc) # 创建线程 t1=threading.Thread(target=test,args=("我是子线程t1",)) #第一个参数值是函数名,第二个参数值是元组类型 t2=threading.Thread(target=test,args=("我是子线程t2",)) #启动线程 t1.start() t2.start() for i in range(3): time.sleep(1) print("我是主线程输出的内容。。。。")
以上代码中一共有了3个线程、主线程以及两个子线程。运行代码时,3个线程是并发的,它们会一起竞争CPU资源,运行结果如下:
场景二:使用join ,其中join的作用是:在子线程运行之前、这个子线程的父线程将一直被阻塞 (注意这里是父线程被阻塞)
import threading,time def test(desc): for i in range(5): #循环5次 time.sleep(1) print(desc) def test2(desc): for i in range(8): #循环8次 time.sleep(1) print(desc) # 创建线程 t1=threading.Thread(target=test,args=("我是子线程t1",)) t2=threading.Thread(target=test2,args=("我是子线程t2",)) #启动线程 t1.start() t2.start() # join 这里只是子线程t1使用了join t1.join() for i in range(3): time.sleep(1) print("我是主线程输出的内容。。。。")
最终的运行结果为:
场景三:该场景下又分为两种情况、情况一:所有进程都守护主线程
import threading,time def test(desc): for i in range(10): time.sleep(1) print(desc) def test2(desc): for i in range(7): time.sleep(1) print(desc) # 创建线程 t1=threading.Thread(target=test,args=("我是子线程t1",)) t2=threading.Thread(target=test2,args=("我是子线程t2",)) #t1和t2都守护进程 t1.setDaemon(True) t2.setDaemon(True) #启动线程 t1.start() t2.start() for i in range(5): time.sleep(1) print("我是主线程输出的内容。。。。")
运行结果:
情况二:只有线程t1守护主线程、就是情况一的基础下、把 t2.setDaemon(True)注释掉、运行结果如下:
守护线程总结:以上举例了两种线程守护的情况、这里的线程守护、守护的其实是主线程。如上面的t1.setDaemon() 就是子线程t1守护主线程、也就是说主线程运行完就可以了、不用管t1有没有运行完。可能有人就会有情况二截图中的疑惑、觉得t1不是已经守护线程了吗、怎么主线程都运行完了、它还可以运行?其实是因为上面创建了两个子线程 t1和t2, 但是只有t1是守护线程的。所以主线程运行完的时候还会去检查没有守护进程的子线程t2运行完没、最后发现它没运行完,这时候主线程就不能退出、得等到它运行完。又因为主线程没有退出、而且线程t1也没运行完,那么它就会继续运行,所以就会出现上面这种情况了。
注意:join()和setDaemon(True) 是不能同时使用的、逻辑上有漏洞