首页 > 编程语言 >python多线程程序设计 之一

python多线程程序设计 之一

时间:2024-09-17 09:22:56浏览次数:8  
标签:None 调用 run python 子类 threading 线程 程序设计 多线程

python多线程程序设计 之一


由于Python编程语言的规范实现的全局解释器锁,一次只有一个线程可以执行Python代码。

如果您希望应用程序更好地利用多核机器的计算资源,使用multiprocessing或concurrent.futures.ProcessPoolExecutor。然而,如果您想同时运行多个 I/O 密集型任务,线程仍然是一个合适的模型

全局解释器锁

CPython 解释器使用的一种机制,确保一次只有一个线程执行 Python 字节码。这使对象模型在并发访问的情况下,是安全,简化了 CPython 实现。锁定整个解释器,使解释器更容易成为多线程,但代价是,损失了多处理器机器提供的大部分并行性。

线程APIs

threading.active_count()

返回当前活动的 Thread 对象的数量。返回的计数等于enumerate() 返回的列表的长度。

threading.current_thread()

返回当前 Thread 对象,对应于调用者的控制线程。如果调用者的控制线程不是通过线程模块创建的,则返回一个功能有限的虚拟线程对象。

threading.excepthook(args, /)

处理 Thread.run() 引发的未捕获异常。
args 参数具有以下属性:

  • exc_type:异常类型。
  • exc_value:异常值,可以为None。
  • exc_traceback:异常回溯,可以为None。
  • thread:引发异常的线程,可以为 None。

如果 exc_type 是 SystemExit,则异常将被静默忽略。否则,异常将显示在sys.stderr 上。
如果此函数引发异常,则会调用 sys.excepthook() 来处理它。

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

threading.get_native_id()

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

threading.main_thread()

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

threading.stack_size([size])

返回创建新线程时,使用的线程堆栈大小。可选的参数size指定用于后续被创建的线程的堆栈大小。并且,其值必须为 0(使用平台或配置的默认值)或至少为 32,768 (32 KiB) 的正整数值。如果未指定size,则使用值0。如果不支持更改线程堆栈大小,则会引发运行时错误。如果指定的堆栈大小无效,则会引发 ValueError,并且堆栈大小不变。 32 KiB 是当前支持的最小堆栈大小值,以保证解释器本身有足够的堆栈空间。

某些平台可能对堆栈大小的值有特殊限制,例如要求最小堆栈大小 > 32 KiB,或要求以系统内存页面大小的倍数进行分配。

线程对象

Thread 类表示在单独的控制线程中运行的活动。有两种方法可以指定活动

  1. 把可调用对象传递给线程构造函数
  2. 重写子类中的 run() 方法,子类中不应重写其他方法。换句话说,只重写该类的 init() 和 run() 方法。

一旦创建了线程对象,就必须通过调用线程的 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)

  • group,应该是None;保留,用于将来扩展ThreadGroup 类。
  • target,是run() 方法可调用的对象。默认为 None,表示不调用任何内容。
  • name,是线程名称。默认情况下,唯一名称的构造形式为“Thread-N”,其中 N 是一个小十进制数,或者为“Thread-N (target)”,其中“target”是target.name(如果指定了target参数)。
  • args,是目标调用的参数列表或元组。默认为()。
  • kwargs,是目标调用的关键字参数的字典。默认为 {}。
  • daemon,如果不是 None,则设置线程是为守护线程。如果 None (默认值),则守护进程属性将从当前线程继承。

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

start/run

  1. start, 启动线程的活动。每个线程对象,最多只能调用start一次。它在单独的控制线程中,调用对象的 run() 方法。如果在同一个线程对象上,多次调用start,将产生RuntimeError。
  2. run, 表示线程活动的方法。run() 方法调用一个可调用的对象,这个可调用对象是由构造器的target参数传递给子类的。构造器的参数args和kwargs就是可调用对象的参数。

join

join引起调用线程等待,直到调用 join() 方法的线程终止。也可能未处理的异常终止线程,或可选的超时引起线程终止。

当timeout参数存在,且非 None 时,它​​应该是一个浮点数,指定以秒(或其分数)为单位的操作超时。由于 join() 总是返回 None,因此必须在 join() 之后,调用 is_alive() 来判断是否发生超时。如果线程仍然存活,则 join() 调用超时。

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

一个线程可以被连接多次。

如果尝试join() 当前线程,产生RuntimeError异常,因为这会导致死锁。在线程启动之前,join() 线程也是一个错误,它会引发相同的异常。

线程子类

把threading.Thread作为基类的推导类,产生的类都是线程子类。

子类有两种方法指定活动

  1. 把可调用对象传递给线程构造函数
  2. 重写子类中的 run() 方法,子类中不应重写其他方法。换句话说,只重写该类的 init() 和 run() 方法。

实列代码

该实列使用两种不同的方法实现两个线程子类的活动。

  • Producer是一个可调用对象,使用线程构造函数,产生线程,该线程的run函数调用该可调用对象。
  • Consumer是一个线程子类,该子类包含他自己的run方法,这个方法就是该子类的活动。

这两个子线程使用不同的方法,传递运行参数。

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();

标签:None,调用,run,python,子类,threading,线程,程序设计,多线程
From: https://blog.csdn.net/IT_Beijing_BIT/article/details/142268880

相关文章

  • 【PAT_Python解】1014 福尔摩斯的约会
    原题链接:PTA|程序设计类实验辅助教学平台Tips:以下Python代码仅个人理解,非最优算法,仅供参考!ls=[]#装输入数据,你也可以S1,S2,S3,S4=input(),···D,H,M='','',''dict={'A':'MON','B':'TUE','C':'WED','D�......
  • 基于Python+Vue开发的体育用品商城管理系统
    项目简介该项目是基于Python+Vue开发的体育用品商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Python编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Python的体育用品销售商城管理系统项目,大学生可以在实践中学习......
  • 基于Python+Vue开发的大学竞赛报名管理系统
    项目简介该项目是基于Python+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Python编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Python的大学竞赛报名管理系统项目,大学生可以在实践中学习和提......
  • 3295:【例50.1】陶陶摘苹果(C、C++、python)
    3295:【例50.1】陶陶摘苹果信息学奥赛一本通-编程启蒙(C++版)在线评测系统[例50.1]陶陶摘苹果1930:【05NOIP普及组】陶陶摘苹果信息学奥赛一本通(C++版)在线评测系统陶陶摘苹果(非数组版)陶陶摘苹果(非数组版)_哔哩哔哩_bilibili陶陶摘苹果(非数组版)_哔哩哔哩_bilibili......
  • 2022高教社杯全国大学生数学建模竞赛C题 问题一(1) Python代码演示
    目录问题11.1对这些玻璃文物的表面风化与其玻璃类型、纹饰和颜色的关系进行分析数据探索--单个分类变量的绘图树形图条形图扇形图雷达图Cramer’sV相关分析统计检验列联表分析卡方检验Fisher检验绘图堆积条形图分组条形图分类模型......
  • esp32之micropython 配网代码
    esp32之micropython配网代码最近学习esp32的时候想着能不能给设备自动配网,查了下网上有smartconfig配网但是我无法配置成功所以自己写了AP配网。AP配网代码importnetworkimportsocket,jsonfrommachineimportPin,Timerimporttimeled_pin=Pin(4,Pin.OUT)#配置热......
  • 基于Python的自然语言处理系列(9):使用TorchText与预训练词嵌入进行新闻分类
            在前一篇文章中,我们展示了如何使用TorchText和RNN进行新闻分类。在这篇文章中,我们将改进之前的模型,通过使用预训练词嵌入、优化器的更改、正交初始化以及打包填充序列的技巧,提升模型的学习效率和效果。1.改进方向提高模型学习效果:使用预训练词嵌入:使用Fast......
  • 基于Python的人工智能应用案例系列(2):分类
            在本篇文章中,我们将探讨分类问题,具体的应用场景是贷款审批预测。通过该案例,我们将学习如何使用Python处理分类问题,训练模型并预测贷款是否会被批准。案例背景        该数据集包含贷款申请的相关信息,目标是预测贷款是否会被批准(Loan_Status为目标变......
  • 【Azure Developer】通过SDK(for python)获取Azure服务生命周期信息
    问题描述需要通过PythonSDK获取Azure服务的一些通知信息,如:K8S版本需要更新到指定的版本,Azure服务的维护通知,服务处于不健康状态时的通知,及相关的操作建议等内容。 问题解答AzureResourceHealth是Azure提供的一项服务,旨在帮助用户了解其资源的健康状态。通过AzureResource......
  • 【Java】深入理解Java中的多线程同步机制
    一、多线程的数据不一致    当多个线程同时运行时,线程的调度由操作系统决定,程序本身无法决定。因此,任何一个线程都有可能在任何指令处被操作系统暂停,然后在某个时间段后继续执行。    这个时候,一个在单线程模型下不存在的问题就会发生:如果多个线程同时读写共享......