首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python入门系列(八)——多线程

目录:

一、函数方式

二、类的方式

Python中使用线程有两种方式:函数或类。

Python3 通过两个标准库 和 提供对线程的支持。前者是将python2中的模块重命名后的结果,后者为高级模块,对进行了封装。绝大多数情况下,我们只需要使用这个高级模块,比如,在这里!

一、函数方式

我们借助"吃饭睡觉打豆豆"的小故事来一个经典案例,什么?没听过?自!己!度!娘!

首先来一个正常的逻辑,不使用多线程操作:

我们可以看到耗时6s,每个行为耗时2s,,wo*,,怎么十二点了,emmmmm,稳住,稳住。。。。

继续,继续,然后我们使用多线程操作来改写,只有函数执行变了,代码只放执行部分:

借助多线程操作,所有线程并发启动,整个程序运行过程耗时2s,当然,如果线程耗时不同的话,单个线程耗时最多的时间即为程序运行总时间。

join()方法

join()方法用以阻塞主线程,直到调用此方法的子线程完成之后主线程才继续往下运行。白话一点就是当前子线程如果不结束,主线程不允许结束。

这里的确有点绕,以至于有部分开发在这里也是死用,而并不清楚它的实际意义。

我们先来梳理个概念:任何进程默认会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程,这也就是我们使用的多线程,也就是多个子线程。

刚好Python的threading模块有个current_thread()函数,它永远返回当前线程的实例。主线程实例的名字叫MainThread,子线程的名字可以在创建时指定,如果不起名字Python就自动给线程命名为Thread-1,Thread-2……

我们借此来探究下如果不使用join()方法阻塞主线程会怎么样,略改下代码,在每一个函数的开始与结束引入我们的current_thread()函数,即线程开始与结束的位置(代码变工整了有木有!才记起老师的毒打!):

我们可以看到的位置,在子线程sleep的时候,主线程居然就结束了!下面,我们加上join()方法,之改动了main():

此时的位置出现在了最后,也就是说,在三个子线程全部执行完毕后,主线程才退出,这就是join()方法的意义。为什么要等子线程完成主线程才退出呢?我们买下个伏笔在接下来守护线程部分拓展。

线程守护

守护线程,即为了守护主线程而存在的子线程。

如果你设置一个线程为守护线程,就表示你在说这个线程并不重要,在进程退出的时候,不用等待这个线程退出。那就设置这些线程的daemon属性。即在线程开始(thread.start())之前,调用setDeamon()函数,设定线程的daemon标志。(thread.setDaemon(True))就表示这个线程“不重要”。

主线程的结束意味着进程结束,进程整体的资源都会被回收,而理论上进程必须保证非守护线程都运行完毕后才能结束,这也就是我们为什么要使用join()方法的原因。

我们对上面讨论join()方法时用到的例子进行改写(只变更函数):

我们可以看到,守护线程完全是与join()相对的,守护线程会随着主线程的退出而退出,而join()方法却是阻塞主线程直到子线程执行完毕、主线程最终才退出。

这两种逻辑的选择根据我们的需求自行调整。

二、类的方式

类中多线程的使用是从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法。

老规矩,改写上方打豆豆的例子(工整再升级有没有,有没有意义不重要,代码好看是一种自我修养):

线程同步

同样,类这边我们同样也丢一个知识点,线程同步问题,即线程锁的问题。

threading涉及到两种锁:Lock和RLock,这两种琐的主要区别是:RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐,RLock从一定程度上可以避免死锁情况的出现。

此处,简单逻辑我们以Lock锁为例改写我们上面的例子:

大家可以看到,所有子线程是一个接一个执行的,前一个子线程结束,后一个子线程开始,而非并发执行。线程同步问题正是为了解决多个线程共同对某个数据修改的情况,避免出现不可预料的结果,保证数据的正确性。

其实,多线程这里的内容远没有结束,但作为入门系列教程暂时只到这里,剩余内容会在后边的项目实践中逐步涉及,包括线程优先级队列、线程池管理、开源消息队列等。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190121G1BNLQ00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券