如果您希望应用程序更好地利用多核机器的计算资源,使用multiprocessing或concurrent.futures.ProcessPoolExecutor。然而,如果您想同时运行多个 I/O 密集型任务,线程仍然是一个合适的模型
CPython 解释器使用的一种机制,确保一次只有一个线程执行 Python 字节码。这使对象模型在并发访问的情况下,是安全,简化了 CPython 实现。锁定整个解释器,使解释器更容易成为多线程,但代价是,损失了多处理器机器提供的大部分并行性。
返回当前活动的 Thread 对象的数量。返回的计数等于enumerate() 返回的列表的长度。
返回当前 Thread 对象,对应于调用者的控制线程。如果调用者的控制线程不是通过线程模块创建的,则返回一个功能有限的虚拟线程对象。
处理 Thread.run() 引发的未捕获异常。
args 参数具有以下属性:
如果 exc_type 是 SystemExit,则异常将被静默忽略。否则,异常将显示在sys.stderr 上。
如果此函数引发异常,则会调用 sys.excepthook() 来处理它。
可以重写 threading.excepthook() 以控制如何处理 Thread.run() 引发的未捕获异常。
返回内核分配的当前线程的本机整数线程 ID。这是一个非负整数。它的值可用于在系统范围内唯一标识该特定线程(直到线程终止,之后该值可由操作系统回收)。
返回主线程对象。正常情况下,主线程是Python解释器启动的线程。
返回创建新线程时,使用的线程堆栈大小。可选的参数size指定用于后续被创建的线程的堆栈大小。并且,其值必须为 0(使用平台或配置的默认值)或至少为 32,768 (32 KiB) 的正整数值。如果未指定size,则使用值0。如果不支持更改线程堆栈大小,则会引发运行时错误。如果指定的堆栈大小无效,则会引发 ValueError,并且堆栈大小不变。 32 KiB 是当前支持的最小堆栈大小值,以保证解释器本身有足够的堆栈空间。
某些平台可能对堆栈大小的值有特殊限制,例如要求最小堆栈大小 > 32 KiB,或要求以系统内存页面大小的倍数进行分配。
Thread 类表示在单独的控制线程中运行的活动。有两种方法可以指定活动
一旦创建了线程对象,就必须通过调用线程的 start() 方法来启动其活动。这会在单独的控制线程中调用 run() 方法。
一旦线程的活动开始,该线程就被认为是“活动的”。当它的 run() 方法正常终止,或通过引发未处理的异常终止时,它就停止活动。 is_alive() 方法测试线程是否存活。
其他线程可以调用一个线程的 join() 方法。这会阻塞调用线程,直到调用 join() 方法的线程终止。
线程有一个名称。名称可以传递给构造函数,并通过 name 属性读取或更改。如果 run() 方法引发异常,则会调用 threading.excepthook() 来处理它。默认情况下,threading.excepthook() 会默默地忽略 SystemExit。
线程可以被标记为“守护线程”。该标志的意义在于,当只剩下守护线程时,整个Python程序就会退出。初始值是从创建线程继承的。该标志可以通过 daemon 属性,或daemon构造函数参数来设置。有一个“主线程”对象;它是Python程序中的初始控制线程。它不是守护线程。有可能创建“虚拟线程对象”。这些是与“外来线程”相对应的线程对象,这些线程是在线程模块外部启动的控制线程,例如直接从 C 代码启动。
threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
如果子类重写构造函数,则必须确保,在对线程执行任何其他操作之前,调用基类构造函数 (Thread.init())。
join引起调用线程等待,直到调用 join() 方法的线程终止。也可能未处理的异常终止线程,或可选的超时引起线程终止。
当timeout参数存在,且非 None 时,它应该是一个浮点数,指定以秒(或其分数)为单位的操作超时。由于 join() 总是返回 None,因此必须在 join() 之后,调用 is_alive() 来判断是否发生超时。如果线程仍然存活,则 join() 调用超时。
当timeout参数不存在,或为 None 时,操作将阻塞,直到线程终止。
一个线程可以被连接多次。
如果尝试join() 当前线程,产生RuntimeError异常,因为这会导致死锁。在线程启动之前,join() 线程也是一个错误,它会引发相同的异常。
把threading.Thread作为基类的推导类,产生的类都是线程子类。
子类有两种方法指定活动
该实列使用两种不同的方法实现两个线程子类的活动。
这两个子线程使用不同的方法,传递运行参数。
import threading
import random
def Producer(v1, v2, v3, name, age):
print("Producer args: {0} name:{1} age : {2}".format([v1,v2,v3], name, age))
class Consumer(threading.Thread):
def __init__(self, key_dict):
super(Consumer,self).__init__()
self.keys = key_dict
print("Consumer")
def run(self):
print("dict: {0}".format(self.keys))
if __name__ == "__main__":
v_list = [1,2,3]
keys = {"name":"John", "age":"50"}
producer = threading.Thread(target=Producer, args=v_list, kwargs=keys)
consumer = Consumer(keys)
producer.start();
consumer.start();
producer.join()
consumer.join();