深入认识Python线程中join()函数
发布时间:2021-11-12 11:59:23 所属栏目:教程 来源:互联网
导读:首先先简单介绍下守护线程: 守护线程的工作方式类似服务器,只要没有客户端发来请求,就一直运行并且保持空闲,很像是后台。threading模块建立的线程除了守护线程之外,其余的线程都会在主线程结束之前结束掉。也就是说一般会先解决非守护线程的,所以相比而
首先先简单介绍下守护线程: 守护线程的工作方式类似服务器,只要没有客户端发来请求,就一直运行并且保持空闲,很像是后台。threading模块建立的线程除了守护线程之外,其余的线程都会在主线程结束之前结束掉。也就是说一般会先解决非守护线程的,所以相比而言,守护线程好像就“没那么重要”。设置守护线程使用thread.daemon = True,要在线程启动之前就设置好。 threading模块中join()的作用是为了防止子线程没结束主线程就先结束了,join()对于创建的普通的线程(除了守护线程)是没有多大作用的,有跟没有一样,都是要等到子线程结束后才会执行主线程。守护线程相比普通的线程显得“没有那么重要”,所以主线程一般不等它结束就先结束了。如果是作为守护线程使用join(),那么就会等待守护线程结束后才会执行主线程。 下面对默认的普通线程(即非守护线程)使用join()、不使用join(),和守护线程使用join()、不使用join()进行了分析: 普通线程(即非守护线程)使用join(): import threading def Thread_1(num): print('Thread_1 start') for i in range(num): print('喵') print('Thread_1 end') def Thread_2(num): print('Thread_2 start') for i in range(num): print('呱') print('Thread_2 end') if __name__ == '__main__': thread_list = [] thread_1 = threading.Thread(target=Thread_1, args=(3,)) thread_2 = threading.Thread(target=Thread_2, args=(3,)) #thread_1.daemon = True #thread_2.daemon = True thread_list.append(thread_1) thread_list.append(thread_2) for i in thread_list: i.start() for i in thread_list: i.join() print('全搞定了.......') 运行结果是这样的: 深入理解Python线程中join()函数 可以看到主线程打印的“全搞定了”是在两个线程执行完了之后才执行的,表明主线程会等待子线程执行完毕再结束。 再看看普通线程(即非守护线程)不使用join(),会不会效果不一样: import threading def Thread_1(num): print('Thread_1 start') for i in range(num): print('喵') print('Thread_1 end') def Thread_2(num): print('Thread_2 start') for i in range(num): print('呱') print('Thread_2 end') if __name__ == '__main__': thread_list = [] thread_1 = threading.Thread(target=Thread_1, args=(3,)) thread_2 = threading.Thread(target=Thread_2, args=(3,)) # thread_1.daemon = True # thread_2.daemon = True thread_list.append(thread_1) thread_list.append(thread_2) for i in thread_list: i.start() # for i in thread_list: # i.join() print('全搞定了.......') 结果跟上面的普通线程使用join()的一模一样(如下图),说明有没有join()对于非守护线程无所谓。 深入理解Python线程中join()函数 现在来试下守护线程不加上join(),也就是说很可能主线程先结束了子线程还没结束: import threading def Thread_1(num): print('Thread_1 start') for i in range(num): print('喵') print('Thread_1 end') def Thread_2(num): print('Thread_2 start') for i in range(num): print('呱') print('Thread_2 end') if __name__ == '__main__': thread_list = [] thread_1 = threading.Thread(target=Thread_1, args=(3,)) thread_2 = threading.Thread(target=Thread_2, args=(3,)) thread_1.daemon = True thread_2.daemon = True thread_list.append(thread_1) thread_list.append(thread_2) for i in thread_list: i.start() # for i in thread_list: # i.join() print('全搞定了.......') 结果跟我们预期的一样,thread_2还没’呱‘完和打印‘Thread_2 end’,主线程就说“全搞定了........”: 深入理解Python线程中join()函数 我们现在决定让守护线程变得“重要起来”,所以使用join(),强制让守护线程在主线程之前结束: import threading def Thread_1(num): print('Thread_1 start') for i in range(num): print('喵') print('Thread_1 end') def Thread_2(num): print('Thread_2 start') for i in range(num): print('呱') print('Thread_2 end') if __name__ == '__main__': thread_list = [] thread_1 = threading.Thread(target=Thread_1, args=(3,)) thread_2 = threading.Thread(target=Thread_2, args=(3,)) thread_1.daemon = True thread_2.daemon = True thread_list.append(thread_1) thread_list.append(thread_2) for i in thread_list: i.start() for i in thread_list: i.join() print('全搞定了.......') 果然是可以的,直接就把守护线程拉到了主线程之前完成: 深入理解Python线程中join()函数 其实join()还可以加个参数,让主线程等待多久,如果等了那么长时间守护线程还不结束那么主线程就要强制关闭了: import threading import time def Thread_1(num): print('Thread_1 start') for i in range(num): time.sleep(5) print('喵') print('Thread_1 end') if __name__ == '__main__': thread_1 = threading.Thread(target=Thread_1, args=(3,)) thread_1.daemon = True thread_1.start() thread_1.join(6) print('全搞定了.......') 我这里主线程只给你6秒的时间,你“喵”一次就5秒,6秒一到我就不管你直接结束了,所以得到的结果应该是只能“喵”一次。 深入理解Python线程中join()函数 那不是守护线程使用join(6)会怎么样呢?由于普通子线程地位很高啊...所以哪怕是等了6秒,主线程继续执行自己的代码后,到最后还是会慢慢执行子线程的代码直到结束,是不是很气人…… 总的来说join()方法可以提升守护线程地位以及设置主线程等待子线程的时间。普通线程跟守护线程就很像你女票和普通人,假设你是主线程,你等女票的时候,无论女票多晚到你都得等她,但是你等普通人的时候你就可以说我有事先溜了。如果讲的这么清楚你还是听不懂的话那只能说明一个问题:你没有女票! ![]() (编辑:PHP编程网 - 黄冈站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |