threading ---基于线程的并行性

源代码: Lib/threading.py


此模块在较低级别之上构造较高级别的线程接口 _thread 模块。也见 queue 模块。

在 3.7 版更改: 这个模块以前是可选的,现在总是可用的。

注解

虽然它们没有在下面列出,但是 camelCase 在python 2.x系列中,用于此模块中某些方法和函数的名称仍然受此模块支持。

本模块定义以下功能:

threading.active_count()

返回 Thread 对象当前处于活动状态。返回的计数等于 enumerate() .

threading.current_thread()

返回电流 Thread 对象,对应于调用方的控制线程。如果调用方的控制线程不是通过 threading 模块,返回功能有限的虚拟线程对象。

threading.excepthook(args, /)

处理由引发的未捕获异常 Thread.run() .

这个 args 参数具有以下属性:

  • exc_type :异常类型。

  • exc_value :异常值,可以是 None .

  • exc_traceback :异常回溯,可以是 None .

  • 线 :引发异常的线程,可以 None .

如果 exc_type 是 SystemExit ,该异常被静默忽略。否则,异常将打印在 sys.stderr .

如果此函数引发异常, sys.excepthook() 调用以处理它。

threading.excepthook() 可以重写以控制引发未捕获异常的方式 Thread.run() 处理。

存储 exc_value 使用自定义钩子可以创建一个引用循环。当不再需要异常时,应该明确地清除它以中断引用循环。

存储 线 如果将自定义钩子设置为正在完成的对象,则可以使用该钩子将其恢复。避免储存 线 自定义钩子完成后,可以避免重新恢复对象。

参见

sys.excepthook() 处理未捕获的异常。

3.8 新版功能.

threading.__excepthook__

保存的原始值为 threading.excepthook() 。保存它的目的是为了在原始值碰巧被损坏或替换的对象替换时恢复原始值。

3.10 新版功能.

threading.get_ident()

返回当前线程的“线程标识符”。这是一个非零整数。它的值没有直接的意义;它被用作一个神奇的cookie,用于索引线程特定数据的字典。当一个线程退出并创建另一个线程时,可以回收线程标识符。

3.3 新版功能.

threading.get_native_id()

返回内核分配的当前线程的本机整数线程ID。这是一个非负整数。它的值可用于唯一地标识这个特定的线程系统范围(直到线程终止,之后该值可由操作系统回收)。

Availability :windows、freebsd、linux、macos、openbsd、netbsd、aix。

3.8 新版功能.

threading.enumerate()

返回所有列表 Thread 对象当前处于活动状态。该列表包括后台线程、由创建的虚拟线程对象 current_thread() 以及主线程。它排除终止的线程和尚未启动的线程。

threading.main_thread()

还主 Thread 对象。在正常情况下,主线程是启动Python解释器的线程。

3.4 新版功能.

threading.settrace(func)

为从中启动的所有线程设置跟踪函数 threading 模块。这个 func 将传递给 sys.settrace() 对于每个线程,在其 run() 方法被调用。

threading.gettrace()

获取由设置的跟踪函数 settrace() 。

3.10 新版功能.

threading.setprofile(func)

为从启动的所有线程设置配置文件函数 threading 模块。这个 func 将传递给 sys.setprofile() 对于每个线程,在其 run() 方法被调用。

threading.getprofile()

获取由设置的分析器函数 setprofile() 。

3.10 新版功能.

threading.stack_size([size])

返回创建新线程时使用的线程堆栈大小。可选的 size 参数指定要用于后续创建的线程的堆栈大小,并且必须为0(使用平台或配置的默认值)或至少为32768(32 kib)的正整数值。如果 size 未指定,使用0。如果不支持更改线程堆栈大小,则 RuntimeError 提高了。如果指定的堆栈大小无效,则 ValueError 被引发,堆栈大小未被修改。32 kib是当前支持的最小堆栈大小值,以确保为解释器本身提供足够的堆栈空间。请注意,有些平台可能对堆栈大小的值有特定的限制,例如要求最小堆栈大小>32 kib或要求以系统内存页面大小的倍数分配-有关更多信息,应参考平台文档(通常使用4 kib页面;使用4096倍数作为堆栈大小是在缺乏更具体信息的情况下,采用GEGSTED方法)。

Availability :Windows,具有POSIX线程的系统。

此模块还定义以下常量:

threading.TIMEOUT_MAX

允许的最大值 timeout 阻塞函数参数 (Lock.acquire() , RLock.acquire() , Condition.wait() 等)。指定大于此值的超时将引发 OverflowError .

3.2 新版功能.

这个模块定义了一些类,这些类在下面的章节中详细介绍。

该模块的设计基于Java的线程模型。然而,在Java中,锁和条件变量是每个对象的基本行为,它们是Python中的独立对象。 Python Thread 类支持Java线程类的行为子集;当前,没有优先级,没有线程组,线程不能被销毁、停止、挂起、恢复或中断。Java线程类的静态方法在实现时被映射到模块级函数。

下面描述的所有方法都是原子执行的。

线程本地数据

线程本地数据是其值特定于线程的数据。要管理线程本地数据,只需创建 local (或子类)并在其上存储属性:

mydata = threading.local()
mydata.x = 1

对于单独的线程,实例的值将不同。

class threading.local

表示线程本地数据的类。

有关更多详细信息和广泛示例,请参见 _threading_local 模块。

线程对象

这个 Thread 类表示在单独的控件线程中运行的活动。指定活动有两种方法:将可调用对象传递给构造函数,或重写 run() 子类中的方法。子类中不应重写任何其他方法(构造函数除外)。换言之, only 覆盖 __init__() 和 run() 此类的方法。

创建线程对象后,必须通过调用线程的 start() 方法。这将调用 run() 方法位于单独的控件线程中。

一旦线程的活动启动,该线程就被认为是“活动的”。当它 run() 方法终止——正常情况下,或者通过引发未处理的异常来终止。这个 is_alive() 方法测试线程是否活动。

其他线程可以调用线程的 join() 方法。这会阻塞调用线程,直到 join() 方法被调用终止。

线程有一个名称。可以将名称传递给构造函数,并通过 name 属性。

如果 run() 方法引发异常, threading.excepthook() 调用以处理它。默认情况下, threading.excepthook() 默默地忽略 SystemExit .

线程可以标记为“守护进程线程”。这个标志的意义在于,当只剩下守护进程线程时,整个python程序就会退出。初始值从创建线程继承。可以通过 daemon 属性或 守护进程 构造函数参数。

注解

守护进程线程在关闭时突然停止。它们的资源(如打开的文件、数据库事务等)可能无法正确释放。如果希望线程正常停止,请使其非守护进程,并使用适当的信号机制,如 Event .

有一个“主线程”对象;这对应于Python程序中的初始控制线程。它不是守护进程线程。

可能会创建“虚拟线程对象”。这些是对应于“外来线程”的线程对象,这些线程是在线程模块外部启动的控制线程,例如直接从C代码启动。虚拟线程对象的功能有限;它们总是被认为是活动的和后台的,不能 join() 因为不可能检测到外线程的终止,所以它们不会被删除。

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

应始终使用关键字参数调用此构造函数。参数是:

group 应该是 None ;保留供将来扩展时 ThreadGroup 类已实现。

目标 可调用对象是否由 run() 方法。默认为 None ,表示没有调用任何内容。

name 是线程名称。默认情况下,一个唯一的名称是以“Thread”的形式构造的- N “哪里 N 是一个小的十进制数,或“线程”- N (target)“目标”在哪里 target.__name__ 如果 目标 参数已指定。

args 是目标调用的参数元组。默认为 () .

关键字参数 是用于目标调用的关键字参数字典。默认为 {{}} .

如果没有 None , 守护进程 显式设置线程是否为后台线程。如果 None (默认值),daemonic属性从当前线程继承。

如果子类重写构造函数,它必须确保调用基类构造函数 (Thread.__init__() )在对线程执行其他操作之前。

在 3.10 版更改: 使用 目标 如果 name 参数被省略。

在 3.3 版更改: 增加了 守护进程 参数。

start()

启动线程的活动。

每个线程对象最多必须调用一次。它为对象的 run() 要在单独的控件线程中调用的方法。

此方法将引发 RuntimeError 如果在同一线程对象上多次调用。

run()

表示线程活动的方法。

可以在子类中重写此方法。标准 run() 方法调用作为 目标 参数(如果有),其中位置参数和关键字参数取自 args 和 关键字参数 分别是论点。

join(timeout=None)

等待线程终止。这会阻塞调用线程,直到 join() 方法被调用终止——正常或通过未处理的异常终止——或者直到出现可选的超时。

当 timeout 参数存在而不是 None ,它应该是一个浮点数,以秒(或其分数)为单位指定操作超时。AS join() 总是回报 None ,你必须调用 is_alive() 之后 join() 要决定是否发生了超时--如果线程仍然活动,则 join() 调用超时。

当 timeout 参数不存在或 None ,操作将阻塞,直到线程终止。

线程可以是 join() Ed很多次。

join() 提高 RuntimeError 如果试图加入当前线程,会导致死锁。这也是一个错误 join() 一个线程在它被启动之前,试图这样做会引发相同的异常。

name

仅用于标识目的的字符串。它没有语义。多个线程可以具有相同的名称。初始名称由构造函数设置。

getName()
setName()

的旧getter/setter API name ;将其直接用作属性。

ident

此线程的“线程标识符”或 None 如果线程尚未启动。这是一个非零整数。见 get_ident() 功能。当一个线程退出并创建另一个线程时,可以回收线程标识符。即使线程已退出,标识符也可用。

native_id

线程ID (TID )由操作系统(内核)分配的线程。这是一个非负整数,或者 None 如果线程尚未启动。查看 get_native_id() 功能。此值可用于在系统范围内唯一标识此特定线程(直到线程终止,之后该值可由操作系统回收)。

注解

与进程ID类似,从创建线程到终止线程,线程ID仅在系统范围内有效(保证唯一)。

Availability :需要 get_native_id() 功能。

3.8 新版功能.

is_alive()

返回线程是否活动。

此方法返回 True 就在 run() 方法将一直启动到 run() 方法终止。模块功能 enumerate() 返回所有活动线程的列表。

daemon

一个布尔值,指示此线程是守护进程线程(true)还是非(false)。必须在之前设置 start() 被调用,否则 RuntimeError 被引发。它的初始值继承自创建线程;主线程不是守护进程线程,因此在主线程中创建的所有线程默认为 daemon = False .

当没有活动的非守护进程线程时,整个python程序将退出。

isDaemon()
setDaemon()

的旧getter/setter API daemon ;将其直接用作属性。

CPython implementation detail: 在塞顿,由于 Global Interpreter Lock ,一次只能有一个线程执行Python代码(即使某些面向性能的库可能会克服这一限制)。如果您希望应用程序更好地利用多核计算机的计算资源,建议您使用 multiprocessing 或 concurrent.futures.ProcessPoolExecutor . 但是,如果您希望同时运行多个I/O绑定的任务,线程仍然是一个合适的模型。

锁定对象

基元锁是一个同步基元,在锁定时不属于特定线程。在python中,它是当前可用的最低级别的同步原语,由 _thread 扩展模块。

原始锁处于“锁定”或“解锁”两种状态之一。它是在未锁定状态下创建的。它有两种基本方法, acquire() 和 release() . 当状态解锁时, acquire() 将状态更改为锁定并立即返回。当状态被锁定时, acquire() 阻止直到调用 release() 在另一个线程中将其更改为unlocked,然后 acquire() 调用将其重置为锁定并返回。这个 release() 方法只能在锁定状态下调用;它将状态更改为Unlocked并立即返回。如果试图释放未锁定的锁,则 RuntimeError 将被引发。

锁还支持 context management protocol .

当多个线程被阻塞时 acquire() 等待状态变为Unlocked,当 release() 调用将状态重置为UNLOCKED;其中一个等待线程的进程没有定义,并且可能因实现而异。

所有方法都是原子执行的。

class threading.Lock

实现基本锁对象的类。一旦一个线程获得了一个锁,随后将尝试获取它,直到它被释放;任何线程都可以释放它。

注意 Lock 实际上是一个factory函数,它返回平台支持的最有效版本的具体锁类的实例。

acquire(blocking=True, timeout=- 1)

获取一个锁、阻塞或非阻塞。

当使用 blocking 参数设置为 True (默认),锁定直到锁定解除,然后将其设置为锁定并返回 True .

当使用 blocking 参数设置为 False ,不要阻塞。如果调用 blocking 设置为 True 会阻塞,返回 False 立即;否则,将锁设置为锁定并返回 True .

使用浮点调用时 timeout 参数设置为正值,最多阻止由指定的秒数 timeout 只要锁不能被获取。一 timeout 的参数 -1 指定无限制等待。禁止指定 timeout 什么时候? blocking 是假的。

返回值为 True 如果成功获取锁, False 如果没有(例如如果 timeout 过期)

在 3.2 版更改: 这个 timeout 参数是新的。

在 3.2 版更改: 如果底层线程实现支持,那么现在可以通过POSIX上的信号中断锁获取。

release()

释放锁。这可以从任何线程调用,而不仅仅是获取锁的线程。

锁定后,将其重置为解锁,然后返回。如果有其他线程被阻塞,等待锁解锁,则只允许其中一个线程继续。

在未锁定的锁上调用时, RuntimeError 提高了。

没有返回值。

locked()

如果获取了锁,则返回true。

锁定对象

可重入锁是一个同步原语,可以被同一线程多次获取。在内部,它使用“拥有线程”和“递归级别”的概念,以及原始锁使用的锁定/解锁状态。在锁定状态下,某些线程拥有该锁;在未锁定状态下,没有线程拥有该锁。

为了锁定锁,线程调用 acquire() method; this returns once the thread owns the lock. To unlock the lock, a thread calls its release() method. acquire()/release() 调用对可以嵌套;只有final release() (the release() (最外面的一对)将锁重置为解锁,并允许另一个线程阻塞 acquire() 继续进行。

可重入锁还支持 context management protocol .

class threading.RLock

此类实现可重入锁对象。可重入锁必须由获取它的线程释放。一旦一个线程获得了一个可重入锁,同一个线程就可以在不阻塞的情况下再次获得它;该线程必须在每次获得它时释放它一次。

注意 RLock 实际上是一个factory函数,它返回平台支持的最有效版本的具体rlock类的实例。

acquire(blocking=True, timeout=- 1)

获取一个锁、阻塞或非阻塞。

在没有参数的情况下调用时:如果此线程已经拥有锁,则将递归级别增加一个,然后立即返回。否则,如果另一个线程拥有该锁,则阻塞直到该锁被解锁。一旦锁被解锁(不属于任何线程),那么获取所有权,将递归级别设置为1,然后返回。如果有多个线程被阻塞,等待锁被解锁,那么一次只有一个线程能够获取锁的所有权。在这种情况下没有返回值。

当使用 舞台调度 参数设置为true,执行与不带参数调用时相同的操作,然后返回 True .

当使用 舞台调度 参数设置为false,不阻止。如果没有参数的调用会阻塞,则返回 False 立即执行;否则,执行与无参数调用时相同的操作,并返回 True .

使用浮点调用时 超时 参数设置为正值,最多阻止由指定的秒数 超时 只要锁不能得到。返回 True 如果已获取锁,如果超时已过,则为false。

在 3.2 版更改: 这个 timeout 参数是新的。

release()

释放一个锁,减少递归级别。如果减量后为零,则将锁重置为未锁定(不属于任何线程),如果任何其他线程被阻止,等待锁解锁,则只允许其中一个线程继续。如果递减后递归级别仍然为非零,则锁将保持锁定并由调用线程拥有。

只有当调用线程拥有锁时才调用此方法。一 RuntimeError 如果在锁解锁时调用此方法,则引发。

没有返回值。

条件对象

条件变量总是与某种锁相关联;可以传入该锁,或者默认情况下将创建一个锁。当多个条件变量必须共享同一锁时,传入一个非常有用。锁是Condition对象的一部分:您不必单独跟踪它。

条件变量服从 context management protocol 使用 with 语句获取封闭块期间的关联锁。这个 acquire() 和 release() 方法还调用关联锁的相应方法。

必须在保持关联锁的情况下调用其他方法。这个 wait() 方法释放锁,然后阻塞,直到另一个线程通过调用 notify() 或 notify_all() . 一旦觉醒, wait() 重新获取锁并返回。也可以指定超时。

这个 notify() 方法唤醒一个等待条件变量(如果有)的线程。这个 notify_all() 方法唤醒所有等待条件变量的线程。

注: notify() 和 notify_all() 方法不会释放锁;这意味着唤醒的线程不会从它们的 wait() 立即调用,但仅当调用的线程 notify() 或 notify_all() 最后放弃了锁的所有权。

使用条件变量的典型编程样式使用锁来同步对某些共享状态的访问;对特定状态更改调用感兴趣的线程 wait() 重复直到看到所需状态,而修改状态调用的线程 notify() 或 notify_all() 当他们以这样一种方式改变状态时,它可能是一个侍者想要的状态。例如,以下代码是具有无限缓冲容量的一般生产者-消费者情况:

# Consume one item
with cv:
    while not an_item_is_available():
        cv.wait()
    get_an_available_item()

# Produce one item
with cv:
    make_an_item_available()
    cv.notify()

这个 while 循环检查应用程序的条件是必要的,因为 wait() 可以在任意长时间后返回,并提示 notify() 调用可能不再为真。这是多线程编程固有的。这个 wait_for() 方法可用于自动执行条件检查,并简化超timeit算:

# Consume an item
with cv:
    cv.wait_for(an_item_is_available)
    get_an_available_item()

在两者之间选择 notify() 和 notify_all() ,考虑一个状态更改是否只对一个或多个等待线程有意义。例如,在典型的生产者-消费者情况下,向缓冲区添加一个项目只需要唤醒一个消费者线程。

class threading.Condition(lock=None)

此类实现条件变量对象。条件变量允许一个或多个线程等待,直到另一个线程通知它们。

如果 lock 是否给出了参数 None ,必须是 Lock 或 RLock 对象,它用作基础锁。否则,一个新的 RLock 对象被创建并用作基础锁。

在 3.3 版更改: 从factory函数更改为类。

acquire(*args)

获取基础锁。此方法对基础锁调用相应的方法;返回值是该方法返回的值。

release()

释放基础锁。此方法对基础锁调用相应的方法;没有返回值。

wait(timeout=None)

等待直到通知或发生超时。如果调用线程在调用此方法时未获取锁,则 RuntimeError 提高了。

此方法释放基础锁,然后阻塞,直到被 notify() 或 notify_all() 在另一个线程中调用相同的条件变量,或者直到出现可选超时。一旦被唤醒或超时,它就会重新获得锁并返回。

当 timeout 参数存在而不是 None ,它应该是一个浮点数,以秒(或其分数)为单位指定操作超时。

当基础锁是 RLock ,未使用其 release() 方法,因为这可能不会在多次递归获取锁时实际解锁。相反,它的内部接口 RLock 类被使用,即使它已经被递归地获取了好几次,也会真正地解锁它。然后使用另一个内部接口在重新获取锁时恢复递归级别。

返回值为 True 除非给出 timeout 过期,在这种情况下 False .

在 3.2 版更改: 以前,该方法始终返回 None .

wait_for(predicate, timeout=None)

等待条件的计算结果为真。 谓语 应该是可调用的,其结果将被解释为布尔值。A timeout 可提供最大等待时间。

此实用程序方法可以调用 wait() 重复,直到谓词满足为止,或者直到超时为止。返回值是谓词的最后一个返回值,将计算为 False 如果方法超时。

忽略超时功能,调用此方法大致等同于写入:

while not predicate():
    cv.wait()

因此,同样的规则也适用于 wait() :调用时必须保持锁,返回时重新获取锁。谓词是用保持的锁来计算的。

3.2 新版功能.

notify(n=1)

默认情况下,唤醒一个在此条件下等待的线程(如果有)。如果调用线程在调用此方法时未获取锁,则 RuntimeError 提高了。

这种方法最多能唤醒 n 在等待条件变量的线程中;如果没有线程在等待,则为no op。

当前的实现完全唤醒 n 线程,如果至少 n 线程正在等待。然而,依靠这种行为是不安全的。未来,优化的实现有时会比 n 线程。

注意:唤醒的线程实际上不会从其 wait() 调用,直到它可以重新获取锁。自从 notify() 不释放锁,它的调用方应该。

notify_all()

唤醒在此条件下等待的所有线程。这种方法的作用就像 notify() ,但唤醒所有等待线程而不是一个。如果调用线程在调用此方法时未获取锁,则 RuntimeError 提高了。

信号量

这是计算机科学史上最古老的同步原语之一,由早期荷兰计算机科学家Edsger W.Dijkstra发明(他使用了这些名字 P() 和 V() 而不是 acquire() 和 release() )

信号量管理一个内部计数器,该计数器由每个计数器递减 acquire() 调用并递增 release() 调用。计数器永远不能低于零;何时 acquire() 发现它是零,它阻塞,等待其他线程调用 release() .

信号量还支持 context management protocol .

class threading.Semaphore(value=1)

此类实现信号量对象。信号量管理表示 release() 调用数减去 acquire() 调用,加上初始值。这个 acquire() 如果需要,方法将阻塞,直到它可以返回而不使计数器为负。如果没有给出, value 默认值为1。

可选参数给出了 value 用于内部计数器;默认为 1 . 如果 value 给定小于0, ValueError 提高了。

在 3.3 版更改: 从factory函数更改为类。

acquire(blocking=True, timeout=None)

获取信号量。

在没有参数的情况下调用时:

  • 如果内部计数器在输入时大于零,则将其减1并返回 True 立即。

  • 如果输入时内部计数器为零,则阻塞直到被调用 release() . 一旦唤醒(且计数器大于0),将计数器减小1并返回 True . 每次调用 release() . 不应依赖线程的唤醒顺序。

当用调用时 舞台调度 设为false,不要阻塞。如果没有参数的调用会阻塞,则返回 False 立即执行;否则,执行与无参数调用时相同的操作,并返回 True .

当使用 超时 以外 None ,最多阻塞 超时 几秒钟。如果在该时间间隔内获取未成功完成,则返回 False . 返回 True 否则。

在 3.2 版更改: 这个 timeout 参数是新的。

release(n=1)

释放信号量,将内部计数器递增 n . 当它在进入时为零并且其他线程正在等待它再次变大到大于零时,唤醒 n 那些线。

在 3.9 版更改: 增加了 n 参数一次释放多个等待线程。

class threading.BoundedSemaphore(value=1)

类实现有界信号量对象。有界信号量检查以确保其当前值不超过其初始值。如果确实如此, ValueError 提高了。在大多数情况下,信号量用于保护容量有限的资源。如果信号量被释放太多次,这是一个错误的迹象。如果没有给出, value 默认值为1。

在 3.3 版更改: 从factory函数更改为类。

Semaphore 例子

信号量通常用于保护容量有限的资源,例如数据库服务器。在任何资源大小固定的情况下,都应该使用有界信号量。在生成任何工作线程之前,您的主线程将初始化信号量:

maxconnections = 5
# ...
pool_sema = BoundedSemaphore(value=maxconnections)

一旦生成,工作线程在需要连接到服务器时调用信号量的Acquire和Release方法::

with pool_sema:
    conn = connectdb()
    try:
        # ... use connection ...
    finally:
        conn.close()

使用有界信号量减少了导致信号量释放的编程错误比获得的信号量释放更多的可能性。

事件对象

这是线程之间最简单的通信机制之一:一个线程向事件发出信号,另一个线程等待它。

事件对象管理一个内部标志,该标志可以用 set() 方法并用重置为false clear() 方法。这个 wait() 方法阻塞,直到标志为真。

class threading.Event

实现事件对象的类。事件管理一个标志,该标志可以用 set() 方法并用重置为false clear() 方法。这个 wait() 方法阻塞,直到标志为真。标志最初为假。

在 3.3 版更改: 从factory函数更改为类。

is_set()

返回 True 如果且仅当内部标志为真。

set()

将内部标志设置为“真”。等待它成为现实的所有线程都会被唤醒。调用的线程 wait() 一旦标志为真,就不会阻塞。

clear()

将内部标志重置为false。随后,线程调用 wait() 将阻止到 set() 调用以再次将内部标志设置为true。

wait(timeout=None)

阻止,直到内部标志为真。如果输入时内部标志为真,则立即返回。否则,阻塞直到另一个线程调用 set() 将标志设置为“真”,或直到出现可选超时。

当超时参数存在且不存在时 None ,它应该是一个浮点数,以秒(或其分数)为单位指定操作超时。

此方法返回 True 如果且仅当内部标志设置为true,则在等待调用之前或等待开始之后,它将始终返回 True 除非超时并且操作超时。

在 3.1 版更改: 以前,该方法始终返回 None .

定时器对象

这个类表示一个只有经过一定时间后才能运行的操作---计时器。 Timer 是的子类 Thread 因此,还可以作为创建自定义线程的示例。

与线程一样,计时器通过调用 start() 方法。可以通过调用 cancel() 方法。计时器在执行其操作之前等待的间隔可能与用户指定的间隔不完全相同。

例如::

def hello():
    print("hello, world")

t = Timer(30.0, hello)
t.start()  # after 30 seconds, "hello, world" will be printed
class threading.Timer(interval, function, args=None, kwargs=None)

创建将运行的计时器 function 带着参数 args 和关键字参数 关键字参数 之后 间隔 几秒钟过去了。如果 args 是 None (默认)然后将使用空列表。如果 关键字参数 是 None (默认)然后将使用空的dict。

在 3.3 版更改: 从factory函数更改为类。

cancel()

停止计时器,并取消计时器操作的执行。只有当计时器仍处于等待阶段时,此功能才会工作。

屏障对象

3.2 新版功能.

此类提供了一个简单的同步原语,供需要相互等待的固定数量的线程使用。每个线程都试图通过调用 wait() 方法并将阻塞,直到所有线程 wait() 调用。此时,线程将同时释放。

对于相同数量的线程,屏障可以重复使用任意次数。

例如,以下是同步客户机和服务器线程的简单方法:

b = Barrier(2, timeout=5)

def server():
    start_server()
    b.wait()
    while True:
        connection = accept_connection()
        process_server_connection(connection)

def client():
    b.wait()
    while True:
        connection = make_connection()
        process_client_connection(connection)
class threading.Barrier(parties, action=None, timeout=None)

为创建屏障对象 政党 线程数。安 行动 当提供时,是一个可在线程释放时由其中一个线程调用的调用。 timeout 如果没有为指定超时值, wait() 方法。

wait(timeout=None)

穿过障碍物。当所有参与屏障的线程都调用了这个函数时,它们都被同时释放。如果A timeout 它优先于提供给类构造函数的任何类。

返回值是一个介于0到 政党 --1,每个线程不同。这可以用来选择一个线程来进行一些特殊的内务管理,例如:

i = barrier.wait()
if i == 0:
    # Only one thread needs to print this
    print("passed the barrier")

如果一个 行动 已提供给构造函数,其中一个线程将在被释放之前调用它。如果此调用引发错误,则屏障将进入断开状态。

如果调用超时,则屏障将进入断开状态。

此方法可能会引发 BrokenBarrierError 当线程正在等待时,如果屏障被破坏或重置,则出现异常。

reset()

将屏障返回到默认的空状态。任何等待它的线程都将收到 BrokenBarrierError 例外。

请注意,如果有其他线程的状态未知,则使用此函数可能需要一些外部同步。如果一个屏障被打破了,最好是离开它,创建一个新的屏障。

abort()

使屏障处于破损状态。这将导致任何当前或将来调用 wait() 失败与 BrokenBarrierError . 例如,如果某个线程需要中止,请使用此选项,以避免应用程序死锁。

最好是简单地用一个合理的 timeout 值自动防止某个线程出错。

parties

通过屏障所需的线程数。

n_waiting

当前在屏障中等待的线程数。

broken

一个布尔值 True 如果屏障处于破裂状态。

exception threading.BrokenBarrierError

这个例外,是 RuntimeError ,当 Barrier 对象被重置或损坏。

在中使用锁、条件和信号量 with 陈述

此模块提供的所有对象 acquire() 和 release() 方法可以用作 with 语句。这个 acquire() 方法将在输入块时调用,并且 release() 将在块退出时调用。因此,以下代码片段:

with some_lock:
    # do something...

等于:

some_lock.acquire()
try:
    # do something...
finally:
    some_lock.release()

目前, Lock , RLock , Condition , Semaphore 和 BoundedSemaphore 对象可以用作 with 语句上下文管理器。