10.2.2 Thread类

10.2.2 Thread类

1.创建线程

Thread类是threading模块中最常用的功能,通过调用用户指定的函数func,独立生成一个活动的线程。

调用用户指定的函数func有两种方式。

①在Thread创建实例对象时,把func以参数形式传递给构造函数。

②通过继承Thread类,并重写run()方法,调用func函数。在Thread的子类中,只允许对__init__()和run()方法进行重写。

对应到操作时,使用Thread类来创建管理线程对象,有两种方式。

方法一,传递给Thread对象一个可执行方法:

方法二,定义子类,父类为threading.Thread,并重写run()方法:

其中Thread类的构造函数调用形式如下:

①group参数:用于保留,作为将来的扩展功能。可以忽略该参数,或调用group=None。

②target参数:设置线程需要执行的自定义函数func,如target=func,设置完成后,被run()方法调用,不设置,则线程不执行任何操作。

③name参数:指定需要执行的线程名称。不指定时,该类自动生成一个Thread-N形式的线程名称。

④kwargs参数:当自定义函数func带有参数时,把参数以元组的形式通过kwargs传递给func。

⑤daemon参数:通过设置False或True确定是否守护线程,当为None时,守护线程属性将会继承父线程的状态(主线程默认情况下都为非)。

【案例10-2】 用传递函数的方式创建两个线程,分别输出指定范围的数值,代码如下:

运行结果如图10-2所示。

可以发现两个线程同时输出,即两个线程并发运行。

【案例10-3】 用继承的方式生成多个列表,代码如下:

图10-2 案例10-2程序运行结果

运行结果如图10-3所示。

图10-3 案例10-3程序运行结果

同样可以发现多个线程是并发的,多个线程同时输出列表元素,结果会出现“你中有我,我中有你”的现象。

2.Thread的主要成员

创建线程后,可以调用其start()方法来启动,该方法会自动调用该类对象的run()方法,此时线程处于alive状态,直到线程的run()方法运行结束。Thread对象的主要方法如表10-3所示。

表10-3 Thread对象的主要方法

续表

一旦一个线程对象被创建,其活动必须通过调用线程的start()方法来启动,然后再调用run()方法来执行用户自定义的函数。

图10-2、图10-3中出现的乱序现象则可以由join()阻塞线程来解决。join()方法在run()方法后执行,这会阻塞调用线程,直到调用join()方法的线程运行终止,才能执行后续代码。

为案例10-2的代码添加join()方法,改进代码如下:

运行结果:

为案例10-3的代码添加join()方法,改进代码如下:

运行结果: