python的并发执行(多线程详解上)(针对小白2)

python的并发执行(多线程详解上)(针对小白2)

前言

这一篇详细说下python的多线程。多线程原计划是一篇写完的,写着写着发觉内容有点多,所以决定把剩下的部分放到下一篇。(写后吐槽:感觉只需要看完简单使用和复杂理解的最前面部分就行了。

python的并发执行 的专栏:https://blog.csdn.net/qq_37924224/category_9852410.html
上一章:《python的并发执行(多线程和多进程的简单使用)(针对小白1)》:https://blog.csdn.net/qq_37924224/article/details/105866342

这一篇参考的主要是官方的手册
threading — 基于线程的并行:https://docs.python.org/zh-cn/3/library/threading.html
源代码:https://github.com/python/cpython/blob/3.8/Lib/threading.py

简单理解

threading:这个是模拟Java线程模型子集的线程模块。
这个模块在较低级的模块 _thread 基础上建立较高级的线程接口。

简单使用

import threading
import time

def print_number(i):
    time.sleep(1)
    print(i)
    
for i in range(10):
    t_thread = threading.Thread(target=print_number,args=(i,))
    t_thread.start()
    #target=后面是你要多线程调用的函数的名称,args=后面是你要调用的函数的输入,注意格式一定是(a,b,c,)

复杂理解

该模块的设计基于 Java的线程模型。 但是,在Java里面,锁和条件变量是每个对象的基础特性,而在Python里面,这些被独立成了单独的对象。 Python 的 Thread 类只是 Java 的 Thread 类的一个子集;目前还没有优先级,没有线程组,线程还不能被销毁、停止、暂停、恢复或中断。 Java 的 Thread 类的静态方法在实现时会映射为模块级函数。

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
调用这个构造函数时,必需带有关键字参数。参数如下:

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

当线程对象一但被创建,其活动一定会因调用线程的 start() 方法开始。这会在独立的控制线程调用 run() 方法。

一旦线程活动开始,该线程会被认为是 ‘存活的’ 。当它的 run() 方法终结了(不管是正常的还是抛出未被处理的异常),就不是’存活的’。 is_alive() 方法用于检查线程是否存活。

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

线程有名字。名字可以传递给构造函数,也可以通过 name 属性读取或者修改。

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

一个线程可以被标记成一个“守护线程”。 这个标志的意义是,当剩下的线程都是守护线程时,整个 Python 程序将会退出。 初始值继承于创建线程。 这个标志可以通过 daemon 特征属性或者 daemon 构造器参数来设置。

注解 守护线程在程序关闭时会突然关闭。他们的资源(例如已经打开的文档,数据库事务等等)可能没有被正确释放。如果你想你的线程正常停止,设置他们成为非守护模式并且使用合适的信号机制,例如: Event。
有个 “主线程” 对象;这对应Python程序里面初始的控制线程。它不是一个守护线程。

“虚拟线程对象” 是可以被创建的。这些是对应于“外部线程”的线程对象,它们是在线程模块外部启动的控制线程,例如直接来自C代码。虚拟线程对象功能受限;他们总是被认为是存活的和守护模式,不能被 join() 。因为无法检测外来线程的终结,它们永远不会被删除。

内部模块介绍及相关作用

  • threading.active_count() 返回当前存活的线程类 Thread 对象。返回的计数等于 enumerate()
    返回的列表长度。
  • threading.current_thread() 返回当前对应调用者的控制线程的 Thread 对象。如果调用者的控制线程不是利用threading 创建,会返回一个功能受限的虚拟线程对象。
  • 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() 引发的未捕获异常的处理方式。
    使用定制钩子存放 exc_value 可能会创建引用循环。 它应当在不再需要异常时被显式地清空以打破引用循环。
    使用定制钩子存放 thread 可能会在它设为被终结对象时将其重生。 请避免在定制钩子完成后存放 thread 以避免对象的重生。
  • threading.get_ident() 返回当前线程的 “线程标识符”。它是一个非零的整数。它的值没有直接含义,主要是用作 magic
    cookie,比如作为含有线程相关数据的字典的索引。线程标识符可能会在线程退出,新线程创建时被复用。
  • threading.get_native_id() 返回内核分配给当前线程的原生集成线程 ID。 这是一个非负整数。
    它的值可被用来在整个系统中唯一地标识这个特定线程(直到线程终结,在那之后该值可能会被 OS 回收再利用)。
  • threading.enumerate() 以列表形式返回当前所有存活的 Thread 对象。
    该列表包含守护线程,current_thread() 创建的虚拟线程对象和主线程。它不包含已终结的线程和尚未开始的线程。
  • threading.main_thread() 返回主 Thread 对象。一般情况下,主线程是Python解释器开始时创建的线程。
  • threading.settrace(func) 为所有 threading 模块开始的线程设置追踪函数。在每个线程的 run()方法被调用前,func 会被传递给 sys.settrace() 。
  • threading.setprofile(func) 为所有 threading 模块开始的线程设置性能测试函数。在每个线程的 run()方法被调用前,func 会被传递给 sys.setprofile() 。
  • threading.stack_size([size]) 返回创建线程时用的堆栈大小。可选参数 size指定之后新建的线程的堆栈大小,而且一定要是0(根据平台或者默认配置)或者最小是32,768(32KiB)的一个正整数。如果 size没有指定,默认是0。如果不支持改变线程堆栈大小,会抛出 RuntimeError 错误。如果指定的堆栈大小不合法,会抛出ValueError错误并且不会修改堆栈大小。32KiB是当前最小的能保证解释器有足够堆栈空间的堆栈大小。需要注意的是部分平台对于堆栈大小会有特定的限制,例如要求大于32KiB的堆栈大小或者需要根据系统内存页面的整数倍进行分配-应当查阅平台文档有关详细信息(4KiB页面比较普遍,在没有更具体信息的情况下,建议的方法是使用4096的倍数作为堆栈大小)。
  • threading.TIMEOUT_MAX 阻塞函数( Lock.acquire(), RLock.acquire(),Condition.wait(), …)中形参 timeout 允许的最大值。传入超过这个值的 timeout 会抛出OverflowError 异常。

结束语

这个内容比想象的多太多了,如果看到这里发觉没解决你的问题,麻烦继续看下一篇。下一篇主要是如何使用和代码咯,
嘿嘿,每周一更完成。加油,一起努力。希望看到这里的同学可以关注,点赞,评论,三连哦。感谢各位!让我们下篇见咯。

猜你喜欢

转载自blog.csdn.net/qq_37924224/article/details/106322699
今日推荐