学科分类
目录

线程的创建和启动

模块threading中定义了Thread类,该类专门用于管理线程。线程的创建方式分为使用Thread类创建和Thread子类创建两种,关于这两种方式的具体介绍如下。

1. 使用Thread类创建线程

可以直接通过Thread类的构造方法Thread()创建线程,该方法的声明如下:

Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

以上方法中,name参数表示线程的名称,默认由“Thread- N”形式组成,其中N为十进制数:其它参数与创建Process对象时用到的参数一致,这里就不再过多赘述了。

需要注意的是,Thread()方法创建线程默认是前台线程,该线程的特点是主线程会等待其执行结束后终止程序。

例如,创建一个Thread类对象thread_one,该对象用于执行task()函数,代码如下。

import threading
from threading import Thread
import time
def task():
  time.sleep(3)
print('子线程运行,名称为:%s'% threading.currentThread().name)
thread_one = Thread(target=task)  # 创建前台线程

使用构造方法创建线程时,还可以将daemon参数设为True,创建一个后台线程。示例如下:

thread_two = Thread(target=task, daemon=True)  # 创建后台线程

后台线程总是与主线程同时终止。

2. 使用Thread子类创建线程

可以自定义一个继承自Thread的子类,在该子类中重写run()方法,再利用子类的构造方法创建线程。run()方法用于实现线程的功能与业务逻辑,可以在子类中重写该方法来自定义线程的行为。例如,定义一个继承自Thread的子类MyThread,该类中重写了__ init()__和run()方法,代码如下。

class MyThread(Thread):
  def __ init__(self, num):
     super().__ init__()        # 调用父类的构造方法完成初始化
     self.name = '线程' + str(num)  # 设置线程的名称
  def run(self):             # 重写的run()方法
     time.sleep(3)
     message = self.name + '运行'
     print(message)

创建一个MyThread类对象,示例如下:

for i in range(3):
  thread_three = MyThread(i)

线程创建完之后,需要调用start()方法进行启动,以真正地将线程转换为就绪状态,等待操作系统地调度。例如,分别启动前面创建的前台线程thread_one、后台线程thread_two和自定义线程thread_three,程序启动和执行的结果分别如下所示:

(1)启动前台线程

thread_one.start()

执行程序,程序在三秒后打印如下信息:

子线程运行,名称为:Thread-1

由此可知,程序中只有一个前台线程和主线程时,它会等待前台线程执行结束后再终止。

(2)启动后台线程

thread_two.start()

执行程序,程序立即结束,没有打印任何信息。由此可知,程序中只有一个后台线程和主线程时,它不会等待后台线程执行结束就立即终止。

(3)启动自定义线程

for i in range(3):
  thread_three = MyThread(i)
  thread_three.start()

程序执行的结果如下所示:

线程1运行
线程0运行
线程2运行

程序中共创建了三个线程,由以上结果可知,每个线程按照自定义的行为输出了相应的语句。

注意:

当一个程序启动时,就有一个进程被操作系统创建,与此同时一个线程也立刻执行,该线程通常叫做程序的主线程(Main Thread)。如果需要再创建新的线程,那么新创建的线程就是主线程的子线程。

Python的threading模块中有个current_thread()函数,它永远返回当前线程的实例。主线程实例的名字叫Main Thread,子线程的名字在创建时可以指定,若没有指定名字,Python自动将线程命名为Thread-1、Thread-2……

点击此处
隐藏目录