第七章 基于线程的并行---threading

本文详细介绍了Python的threading模块,包括线程的状态和转换、线程对象的创建与操作(如start(),run(),join()),以及守护线程和控制流程的相关内容,展示了如何管理和并发执行线程任务。
摘要由CSDN通过智能技术生成

第零章 学前准备
第一章 数据结构 – 基本数据类型
第一章 数据结构 – 字符串
第一章 数据结构 – 列表、元组和切片
第一章 数据结构 – 字典
第一章 数据结构 – 集合
第一章 – 数组、队列、枚举
第一章 数据结构 – 序列分类
第二章 控制流程
第三章 函数也是对象 – 函数定义以及参数
第三章 函数也是对象 – 高阶函数以及装饰器
第三章 函数也是对象 – lambda 表达式、可调用函数及内置函数
第四章 面向对象编程 – 自定义类、属性、方法和函数
第四章 面向对象编程–魔术方法1
第四章 面向对象编程 – 魔术方法2
第四章 面向对象编程 – 可迭代的对象、迭代器和生成器
第四章 面向对象编程 – 继承、接口
第四章 面向对象编程 – 对象引用
第四章 面向对象编程–案例
第五章 文件操作
第六章 异常
第七章 基于线程的并行—threading
第七章 基于线程的并行—锁对象、递归锁对象、条件对象
第七章 基于线程的并行—信号量对象、事件对象、定时器对象、栅栏对象
第八章 常用模块


第七章 基于线程的并行—threading

threading — 基于线程的并行

7.1 线程的状态及转换

  1. 新建状态(New):线程对象被创建后,即处于新建状态。
  2. 就绪状态(Runnable):线程被启动后,进入就绪状态,等待获取 CPU 时间片。
  3. 运行状态(Running):线程获得 CPU 时间片后,进入运行状态,开始执行线程函数。
  4. 阻塞状态(Blocked):线程执行时,如果遇到了某些阻塞操作(如等待 I/O、获取锁等),则进入阻塞状态。
  5. 终止状态(Dead):线程执行完毕后,进入终止状态。



7.1 模块函数

  1. threading.active_count():返回当前存活的 Thread 对象的数量。 返回值与 enumerate() 所返回的列表长度一致。
  2. threading.current_thread():返回当前对应调用者的控制线程的 Thread 对象。如果调用者的控制线程不是利用 threading 创建,会返回一个功能受限的虚拟线程对象。
  3. threading.get_ident():返回当前线程的 “线程标识符”。它是一个非零的整数。它的值没有直接含义,主要是用作 magic cookie,比如作为含有线程相关数据的字典的索引。线程标识符可能会在线程退出,新线程创建时被复用。
  4. threading.enumerate():以列表形式返回当前所有存活的 Thread 对象。 该列表包含守护线程,current_thread() 创建的虚拟线程对象和主线程。它不包含已终结的线程和尚未开始的线程。
  5. threading.main_thread():返回主 Thread 对象。一般情况下,主线程是Python解释器开始时创建的线程。
  6. threading.settrace(func):为所有 threading 模块开始的线程设置追踪函数。在每个线程的 run() 方法被调用前,func会被传递给 sys.settrace()
  7. threading.setprofile(func):为所有 threading 模块开始的线程设置性能测试函数。在每个线程的 run() 方法被调用前,func 会被传递给 sys.setprofile()
  8. threading.stack_size([size]):返回创建线程时用的堆栈大小。可选参数 size 指定之后新建的线程的堆栈大小,而且一定要是0(根据平台或者默认配置)或者最小是32,768(32KiB)的一个正整数。如果 size 没有指定,默认是0。如果不支持改变线程堆栈大小,会抛出 RuntimeError 错误。如果指定的堆栈大小不合法,会抛出 ValueError 错误并且不会修改堆栈大小。32KiB是当前最小的能保证解释器有足够堆栈空间的堆栈大小。需要注意的是部分平台对于堆栈大小会有特定的限制,例如要求大于32KiB的堆栈大小或者需要根据系统内存页面的整数倍进行分配。
  9. threading.TIMEOUT_MAX:阻塞函数( Lock.acquire(), RLock.acquire(), Condition.wait(), …)中形参 timeout 允许的最大值。传入超过这个值的 timeout 会抛出 OverflowError 异常。

7.2 线程对象 threading.Thread

7.2.1 构造函数: class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

  1. group 应该为 None;为了日后扩展 ThreadGroup 类实现而保留。
  2. target 是用于 run() 方法调用的可调用对象。默认是 None,表示不需要调用任何方法。
  3. name 是线程名称。默认情况下,由 "Thread-N" 格式构成一个唯一的名称,其中 N是小的十进制数。
  4. args 是用于调用目标函数的参数元组。默认是 ()
  5. kwargs 是用于调用目标函数的关键字参数字典。默认是 {}
  6. daemon如果不是 None,daemon 参数将显式地设置该线程是否为守护模式。 如果是 None (默认值),线程将继承当前线程的守护模式属性。
  7. 如果子类型重载了构造函数,它一定要确保在做任何事前,先发起调用基类构造器(Thread.__init__())

7.2.2 start()

开始线程活动。它在一个线程里最多只能被调用一次。它安排对象的 run() 方法在一个独立的控制进程中调用。如果同一个线程对象中调用这个方法的次数大于一次,会抛出 RuntimeError 。

7.2.3 run()

代表线程活动的方法。你可以在子类型里重载这个方法。 标准的 run() 方法会对作为 target 参数传递给该对象构造器的可调用对象(如果存在)发起调用,并附带从 argskwargs 参数分别获取的位置和关键字参数。

7.2.4 join(timeout=None)

等待,直到线程终结。这会阻塞调用这个方法的线程,直到被调用 join() 的线程终结 – 不管是正常终结还是抛出未处理异常 – 或者直到发生超时,超时选项是可选的。当 timeout 参数存在而且不是 None 时,它应该是一个用于指定操作超时的以秒为单位的浮点数(或者分数)。因为 join() 总是返回 None ,所以你一定要在 join() 后调用 is_alive() 才能判断是否发生超时 – 如果线程仍然存活,则 join() 超时。当 timeout 参数不存在或者是 None ,这个操作会阻塞直到线程终结。一个线程可以被 join() 很多次。如果尝试加入当前线程会导致死锁, join() 会引起 RuntimeError 异常。如果尝试 join() 一个尚未开始的线程,也会抛出相同的异常。

7.2.5 name

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

7.2.6 ident

这个线程的 ‘线程标识符’,如果线程尚未开始则为 None 。这是个非零整数。参见 get_ident() 函数。当一个线程退出而另外一个线程被创建,线程标识符会被复用。即使线程退出后,仍可得到标识符。

7.2.7 is_alive()

返回线程是否存活。当 run() 方法刚开始直到 run() 方法刚结束,这个方法返回 True 。模块函数 enumerate() 返回包含所有存活线程的列表。

7.2.8 daemon

一个表示这个线程是(True)否(False)守护线程的布尔值。一定要在调用 start() 前设置好,不然会抛出 RuntimeError 。初始值继承于创建线程;主线程不是守护线程,因此主线程创建的所有线程默认都是 daemon = False。当没有存活的非守护线程时,整个Python程序才会退出。

7.2.9 案例

import threading
import time


def target_thread_one(seconds):
    print(f"target_thread_one started! run {seconds} seconds")
    for i in range(1, seconds+1):
        time.sleep(1)
        print(f"target_thread_one runned {i} seconds")
    print("target_thread_one ended!")


def target_thread_dameon(seconds):
    print(f"target_thread_dameon started! run {seconds} seconds")
    for i in range(1, seconds+1):
        time.sleep(1)
        print(f"target_thread_dameon runned {i} seconds")
    print("target_thread_dameon ended!")


class ThreadTwo(threading.Thread):
    def __init__(self, seconds):
        super().__init__()
        self.seconds = seconds

    def run(self):
        print(f"target_thread_two started! run {self.seconds} seconds")
        for i in range(1, self.seconds+1):
            time.sleep(1)
            print(f"target_thread_two runned {i} seconds")
        print("target_thread_two ended!")


if __name__ == "__main__":
    print("main_thread started!")
    thread_one = threading.Thread(
        target=target_thread_one, kwargs={"seconds": 3})
    thread_two = ThreadTwo(5)
    thread_three = threading.Thread(
        target=target_thread_dameon, args=(20,), daemon=True)
    thread_one.start()
    thread_one.join()
    thread_two.start()
    thread_three.start()
    print("main_thread ended!")
main_thread started!
target_thread_one started! run 3 seconds
target_thread_one runned 1 seconds
target_thread_one runned 2 seconds
target_thread_one runned 3 seconds
target_thread_one ended!
target_thread_two started! run 5 seconds
target_thread_dameon started! run 20 seconds
main_thread ended!
target_thread_two runned 1 seconds
target_thread_dameon runned 1 seconds
target_thread_two runned 2 seconds
target_thread_dameon runned 2 seconds
target_thread_dameon runned 3 seconds
target_thread_two runned 3 seconds
target_thread_two runned 4 seconds
target_thread_dameon runned 4 seconds
target_thread_dameon runned 5 secondstarget_thread_two runned 5 seconds
target_thread_two ended!

target_thread_dameon runned 6 seconds
target_thread_dameon runned 7 seconds
target_thread_dameon runned 8 seconds
target_thread_dameon runned 9 seconds
target_thread_dameon runned 10 seconds
target_thread_dameon runned 11 seconds
target_thread_dameon runned 12 seconds
target_thread_dameon runned 13 seconds
target_thread_dameon runned 14 seconds
target_thread_dameon runned 15 seconds
target_thread_dameon runned 16 seconds
target_thread_dameon runned 17 seconds
target_thread_dameon runned 18 seconds
target_thread_dameon runned 19 seconds
target_thread_dameon runned 20 seconds
target_thread_dameon ended!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值