Thread对象
Thread类表示在单独的控制线程中运行的活动。有两种方法可以指定活动:将一个可调用对象传递给构造函数,或者重写子类中的run()
方法。在子类中不应该重写其他方法(构造函数除外)。换句话说,只重写这个类的__init__()
和run()
方法。
一旦线程对象被创建,它的活动必须通过调用线程的start()方法来启动。这将在单独的控制线程中调用run()
方法。
一旦线程的活动启动,线程就被认为是“活的”。当它的run()
方法终止时,它将停止活动——要么正常地终止,要么引发一个未处理的异常。方法的作用是:测试线程是否处于活动状态。
其他线程可以调用线程的join()
方法。这会阻塞调用线程,直到调用join()
方法的线程被终止。
线程有一个名称。名称可以传递给构造函数,并通过name
属性读取或更改。
如果run()
方法引发异常,则调用threading.excepthook()
来处理它。默认情况下,threading.excepthook()
会静默地忽略SystemExit
。
线程可以被标记为“守护线程”。这个标志的意义在于,当只剩下守护线程时,整个Python程序将退出。初始值是从创建线程继承的。这个标志可以通过daemon
属性或daemon
构造函数参数设置。
注意:守护线程在关闭时会突然停止。它们的资源(如打开的文件、数据库事务等)可能没有被正确释放。如果希望线程优雅地停止,请将它们设置为非守护状态,并使用合适的信号机制,如Event。
有一个“主线程”对象;这对应于Python程序中的初始控制线程。它不是守护线程。
有可能会创建“虚拟线程对象”。这些是对应于“外来线程”的线程对象,这些线程是在threading
模块外部启动的控制线程,比如直接从C代码中启动的。虚拟线程对象的功能有限;它们总是被认为是活的和守护的,并且不能被join()
ed。它们永远不会被删除,因为不可能检测到外星线程的终止。
theading.Thread
构造函数
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
args:
参数 | 作用 |
---|---|
group | 应为None ;为将来实现ThreadGroup 类时的扩展保留 |
target | 要由run()方法调用的可调用对象。默认为None,表示不调用任何函数。 |
name | 线程名。默认情况下,唯一的名称以“Thread-N”的形式构造,其中N是一个小的小数 |
args | 是目标调用的参数元组。默认为() 。 |
kwargs | 目标调用的关键字参数字典。默认为{} 。 |
daemon | 如果不是None , daemon 显式设置线程是否为守护线程。如果为None (默认值),守护进程属性将从当前线程继承。 |
如果子类覆盖了构造函数,它必须确保在对线程做任何其他操作之前调用基类构造函数(thread. __init__()
)。
成员方法
函数 | 作用 |
---|---|
start() | 启动线程的活动。每个线程对象最多只能调用它一次。它安排在单独的控制线程中调用对象的run() 方法。如果在同一个线程对象上多次调用此方法,将引发RuntimeError 。 |
run() | 表示线程的活动。可以在子类中重写这个方法。标准run() 方法调用传递给对象构造函数的可调用对象作为目标参数(如果有的话),其位置参数和关键字参数分别取自args 和kwargs 参数。 |
join(timeout=none) | 等待线程结束。这会阻塞调用线程,直到调用join() 方法的线程终止(正常情况下或通过未处理的异常终止),或者直到可选的超时发生。当timeout 参数存在且不是None 时,它应该是一个浮点数,指定操作的超时时间,单位为秒(或以秒为单位的小数)。由于join() 总是返回None ,必须在join() 之后调用is_alive() 来确定是否发生了超时—如果线程仍然处于活动状态,则join() 调用超时。当timeout 参数不存在或为None 时,操作将阻塞,直到线程终止。如果试图连接当前线程,join()将引发RuntimeError,因为这会导致死锁。在线程启动之前join()线程也是一个错误,并且尝试这样做也会引发相同的异常。 |
name | 仅用于标识目的的字符串。它没有语义。多个线程可以被赋予相同的名称。初始名称由构造函数设置。 |
getName() ,setName() | name 使用旧的getter/setter API;请直接将其作为属性使用。 |
ident | 线程的“线程标识符”,如果线程还没有启动则为None 。这是非零整数。请参阅get_ident() 函数。当一个线程退出并创建另一个线程时,线程标识符可能被回收。即使在线程退出后,该标识符也可用。 |
native_id | 此线程的本机积分线程ID。这是非负整数,如果线程还没有启动,则为None 。参见get_native_id() 函数。这表示OS(内核)分配给线程的线程ID (TID)。它的值可以用来在系统范围内唯一地标识这个特定的线程(直到线程终止,之后该值可以被操作系统回收)。 |
is_alive() | 返回线程是否处于活动状态。这个方法在run() 方法开始之前返回True ,直到run() 方法结束之后。模块函数enumerate() 返回所有活动线程的列表。 |
daemon | 一个布尔值,指示该线程是否为守护线程(True)或(False)。这必须在调用start() 之前设置,否则将引发RuntimeError 。它的初始值继承自创建线程;主线程不是守护线程,因此在主线程中创建的所有线程默认为daemon = False 。当没有活的非守护线程剩下时,整个Python程序将退出。 |
isDeamon() ,setDeamon | 旧的API,直接将其作为属性使用 |
代码
import threading
import logging
import time
def thread_func(*args, **kwargs):
logging.info("args: {}".format(args))
logging.info("kwargs: {}".format(kwargs))
time.sleep(1)
def main():
# 创建线程,传递参数args, kwargs
t1 = threading.Thread(target=thread_func, args=(1,2,3), kwargs={"name": "Li", "age": "26"})
# 启动现场
t1.start()
# 阻塞当前线程,直到t1线程执行结束
t1.join()
# 获取线程名
logging.info("Name t1: {}".format(t1.getName()))
# 修改线程名
t1.setName("Thread-t1")
logging.info("Name t1: {}".format(t1.getName()))
# 创建线程
t2 = threading.Thread(target=None)
# 获取现场标识符
logging.info("ident t2: {}".format(t2.ident)) # None, t2 not start
logging.info("ident t1: {}".format(t1.ident))
t2.start()
logging.info("ident t2: {}".format(t2.ident))
# 本机积分线程
logging.info("native_id t1: {}".format(t1.native_id))
# 是否处于活动状态
logging.info("alive t1: {}".format(t1.is_alive()))
logging.info("alive t2: {}".format(t2.is_alive()))
t3 = threading.Thread()
logging.info("alive t1: {}".format(t3.is_alive()))
# 是否为守护线程
t4 = threading.Thread()
logging.info("deamon t4: {}".format(t4.isDaemon()))
# 必须在线程活动之前设置
t4.setDaemon(True)
logging.info("deamon t4: {}".format(t4.daemon))
if __name__ == "__main__":
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%D %H:%M:%S")
main()
结果
09/08/21 01:18:24: args: (1, 2, 3)
09/08/21 01:18:24: kwargs: {'name': 'Li', 'age': '26'}
09/08/21 01:18:25: Name t1: Thread-1
09/08/21 01:18:25: Name t1: Thread-t1
09/08/21 01:18:25: ident t2: None
09/08/21 01:18:25: ident t1: 6152384512
09/08/21 01:18:25: ident t2: 6152384512
09/08/21 01:18:25: native_id t1: 1869050
09/08/21 01:18:25: alive t1: False
09/08/21 01:18:25: alive t2: False
09/08/21 01:18:25: alive t1: False
09/08/21 01:18:25: deamon t4: False
09/08/21 01:18:25: deamon t4: True