threading_python

本文介绍了如何在Python中使用threading.Thread类创建、启动和管理线程,包括构造函数参数、成员方法如start(), run(), join()的用法,以及守护线程、线程名和状态检查等概念。
摘要由CSDN通过智能技术生成

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()方法调用传递给对象构造函数的可调用对象作为目标参数(如果有的话),其位置参数和关键字参数分别取自argskwargs参数。
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值