2.2 Python常用类库threading
如果说Python的简单易用奠定了Python发展的基石,那么丰富的第三方类库给予了Python不断前进的动力。随着科技前沿的发展,Python应用更为丰富,更多涉及不同种类的第三方类库被加入到Python之中。
Python常用类库参见表2.1。
表2.1 Python常用类库
表2.1中给出了Python中常用类库的名称和说明,到目前为止,Python中已经有7000多个可以使用的类库供计算机工程人员以及科学研究人员使用。
2.2.1 threading库的使用
对于希望充分利用计算机性能的程序设计者来说,多线程的应用是必不可少的一个重要技能。多线程类似于使用计算机的一个核心执行多个不同任务。多线程的好处如下:
- 使用线程可以把需要使用大量时间的计算任务放到后台去处理。
- 减少资源占用,加快程序的运行速度。
- 在传统的输入输出以及网络收发等普通操作上,后台处理可以美化当前界面,增加界面的人性化。
本节将详细介绍Python中操作线程的模块:threading,相对于Python既有的多线程模块thread, threading重写了部分API模块,对thread进行了二次封装,重写了更为方便的API来处理线程,从而大大提高了代码执行效率。
2.2.2 threading模块中最重要的Thread类
Thread是threading模块中最重要的类之一,可以使用它来创造线程。其具体使用方法是创建一个threading.Thread对象,在它的初始化函数中将需要调用的对象作为初始化参数传入,具体代码如程序2-2所示。
【程序2-2】
在上述代码中定义的MyThread类中,重写了从父对象继承的run方法,run方法中,将一个全局变量逐一增加。在接下来的代码中,创建了5个独立的对象,分别调用其start方法,最后逐一打印出结果。
可以看到在程序中,每个线程被赋予了一个名字,然后设置每隔0.3秒打印输出本线程的计数,即计数加1。而count被人为地设置成全局共享变量,因此在每个线程中都可以自由地对其进行访问。
程序运行结果如图2.16所示。
图2.16 程序运行结果
通过程序执行结果可以看到,每个线程被起了一个对应的名字,而在运行时候,线程所计算的计数同时增加,这样可以证明,在程序运行过程中2个线程同时对一个数进行操作,并打印其结果。
提示
代码中的run方法和start方法并不是threading自带的方法,而是从Python本身的线程处理模块Thread中继承来的。run方法的作用是在线程被启动以后,执行预先写入的程序代码。一般而言,run方法所执行的内容被称为Activity,而start方法是用于启动线程的方法。
2.2.3 threading中Lock类
虽然线程在程序的执行过程中极大地提高了程序的运行执行效率,但是其带来的影响却难以忽略。例如在上一个程序中,由于每隔一定时间打印当前的数值,应该逐次打印的数据却变成了2个相同的数值被打印出来,因此需要设计一个能够解决这类问题的方案。
Lock类是threading中用于锁定当前线程的锁定类,顾名思义,其作用是对当前运行中的线程进行锁定,只有被当前线程释放后,后续线程才可以继续操作。
import threading lock = threading.Lock() lock.acquire() lock.release()
类中主要代码如上所示。acquire方法提供了确定对象被锁定的标志,release在当前线程使用对象完毕后再将当前对象释放掉。修改后的代码如程序2-3所示。
【程序2-3】
可以看到,Lock被传递给MyThread,并在run方法中人为锁定当前的线程,必须等线程执行完毕后,后续的线程才能继续执行。程序执行结果如图2.17所示。
可以看到,其中变色的部分,线程2只有等线程1完全结束后,才执行后续的操作。本程序中,Thread1等到Thread0完全结束后,才执行第二个操作。
图2.17 程序运行结果
2.2.4 threading中join类
join类是threading中用于堵塞当前主线程的类,其作用是阻止全部的线程继续运行,直到被调用的线程执行完毕或者超时。具体代码如程序2-4所示。
【程序2-4】
程序的运行结果如图2.18所示。
其中的time方法设定了当前的时间,当join启动后,堵塞了调用整体进程的主进程,只有当被堵塞的进程执行完毕后,后续的进程才继续执行。
此外,对于线程的使用,Python还有很多其他的方法,例如threading.Event以及threading.Condition等,这些方法在程序设计时能够极大地帮助我们编写合适的程序。限于篇幅这里不再一一进行介绍,在后续的使用过程中,作者会带领读者了解和掌握更多的相关内容。
图2.18 程序运行结果