Python 中的多线程(01/4)

一、说明

   本文介绍了 Python 编程语言中多线程的基础知识。就像多处理一样,多线程是实现多任务处理的一种方式。在多线程中,使用线程的概念。让我们首先了解 计算机体系结构中线程的概念。

二、线程一般性概念

2.1 什么是 Python 中的进程?

   在计算中,进程是正在执行的计算机程序的实例。任何进程都有 3 个基本组成部分:

  • 可执行程序。
  • 程序所需的相关数据(变量、工作区、缓冲区等)
  • 程序的执行上下文(进程状态)

2.2 Python 线程简介

   线程是进程中的一个实体,可以计划执行。此外,它是可以在 OS(操作系统)中执行的最小处理单元。简单来说,线程是程序中此类指令的序列,可以独立于其他代码执行。为简单起见,您可以假设线程只是进程的子集!线程在线程控制块 (TCB) 中包含所有这些信息:

  • 线程标识符:为每个新线程分配唯一 ID (TID)
  • 堆栈指针:指向进程中线程的堆栈。堆栈包含线程作用域下的局部变量。
  • 程序计数器:存储线程当前正在执行的指令地址的寄存器。
  • 线程状态:可以是“正在运行”、“就绪”、“正在等待”、“正在启动”或“完成”。
  • 线程的寄存器集:分配给线程进行计算的寄存器。
  • 父进程指针:指向线程所在的进程的进程控制块 (PCB) 的指针。

   请考虑下图来了解进程与其线程之间的关系:
在这里插入图片描述
一个进程中可以存在多个线程,其中:

  • 每个线程都包含自己的寄存器集和局部变量(存储在堆栈中)。
  • 进程的所有线程共享全局变量(存储在堆中)和程序代码。

   请考虑下图,了解内存中如何存在多个线程:
在这里插入图片描述

三、Python 中的线程

3.1 简介

   多线程被定义为处理器同时执行多个线程的能力。在简单的单核 CPU 中,它是通过线程之间的频繁切换来实现的。这称为上下文切换。在上下文切换中,每当发生任何中断(由于 I/O 或手动设置)时,都会保存一个线程的状态并加载另一个线程的状态。上下文切换发生得如此频繁,以至于所有线程似乎都在并行运行(这称为多任务处理)。

   请考虑下图,其中进程包含两个活动线程:
在这里插入图片描述

3.2 Python 中的多线程实现步骤

   在 Python 中,threading 模块提供了一个非常简单直观的 API,用于在程序中生成多个线程。让我们尝试一步一步地理解多线程代码。

   第 1 步:导入模块

首先,导入线程模块。

import threading

   第 2 步:创建线程

   为了创建一个新线程,我们创建了一个 Thread 类的对象。它以 ‘target’ 和 ‘args’ 作为参数。target 是线程要执行的函数,而 args 是要传递给目标函数的参数。

t1 = threading.Thread(target, args)
t2 = threading.Thread(target, args)

   第 3 步:启动线程

   要启动线程,我们使用 Thread 类的 start() 方法。

t1.start()
t2.start()

   第 4 步:结束线程执行

   一旦线程启动,当前程序(你可以把它想象成一个主线程)也会继续执行。为了停止当前程序的执行,直到线程完成,我们使用 join() 方法。

t1.join()
t2.join()

   因此,当前程序将首先等待 t1 完成,然后等待 t2 完成。一旦它们完成,就会执行当前程序的其余语句。

3.3 Python 中的多线程案例

   例:让我们考虑一个使用线程模块的简单示例。

   此代码演示了如何使用 Python 的线程模块同时计算数字的平方和立方。创建两个线程 t1 和 t2 来执行这些计算。它们被启动,它们的结果被并行打印,然后程序在两个线程都完成时打印“完成!线程用于在处理计算密集型任务时实现并行性并提高程序性能。

import threading
def print_cube(num):print("Cube: {}" .format(num * num * num))
def print_square(num):print("Square: {}" .format(num * num))
if __name__ =="__main__":t1 = threading.Thread(target=print_square, args=(10,))t2 = threading.Thread(target=print_cube, args=(10,))t1.start()t2.start()t1.join()t2.join()print("Done!")

输出:

Square: 100
Cube: 1000
Done!

在这里插入图片描述
   例:在此示例中,我们使用 os.getpid() 函数来获取当前进程的 ID。我们使用 threading.main_thread() 函数来获取主线程对象。在正常情况下,主线程是启动 Python 解释器的线程。 线程对象的 name 属性用于获取线程的名称。然后我们使用 threading.current_thread() 函数来获取当前的线程对象。

   考虑下面给出的 Python 程序,我们在其中打印每个任务的线程名称和相应的进程。

   此代码演示了os如何使用 Python 的线程模块同时运行两个任务。主程序启动两个线程,t1 和 t2,每个线程负责执行特定任务。线程并行运行,代码提供有关进程 ID 和线程名称的信息。该模块用于访问进程 ID,“threading”模块用于管理线程及其执行。

import threading
import osdef task1():print("Task 1 assigned to thread: {}".format(threading.current_thread().name))print("ID of process running task 1: {}".format(os.getpid()))def task2():print("Task 2 assigned to thread: {}".format(threading.current_thread().name))print("ID of process running task 2: {}".format(os.getpid()))if __name__ == "__main__":print("ID of process running main program: {}".format(os.getpid()))print("Main thread name: {}".format(threading.current_thread().name))t1 = threading.Thread(target=task1, name='t1')t2 = threading.Thread(target=task2, name='t2')t1.start()t2.start()t1.join()t2.join()

输出:

ID of process running main program: 1141
Main thread name: MainThread
Task 1 assigned to thread: t1
ID of process running task 1: 1141
Task 2 assigned to thread: t2
ID of process running task 2: 1141

下图明确了上述概念:
在这里插入图片描述

四、Python 线程池

   线程池是预先创建的线程集合,可以重用来执行多个任务。Python 中的 concurrent.futures 模块提供了一个 ThreadPoolExecutor 类,可以轻松创建和管理线程池。

   在此示例中,我们定义了一个将在线程中运行的函数工作器。我们创建一个最多有 2 个工作线程的 ThreadPoolExecutor。然后,我们使用 submit 方法将两个任务提交到池中。池管理其工作线程中任务的执行。我们使用 shutdown 方法等待所有任务完成,然后主线程继续。

   多线程可以帮助您提高程序的效率和响应速度。但是,在处理线程时要小心,以避免争用条件和死锁等问题。

   此代码使用通过 concurrent.futures.ThreadPoolExecutor 创建的线程池同时运行两个工作器任务。主线程使用 pool.shutdown(wait=True) 等待工作线程完成。这允许在多线程环境中高效地并行处理任务。

import concurrent.futuresdef worker():print("Worker thread running")pool = concurrent.futures.ThreadPoolExecutor(max_workers=2)pool.submit(worker)
pool.submit(worker)pool.shutdown(wait=True)print("Main thread continuing to run")

   因此,这是对 Python 中多线程的简要介绍。本系列的下一篇文章将介绍多个线程之间的同步。 Python 中的多线程 |设置 2(同步)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/417262.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯

前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言4.5key价格泄漏ChatGPT4.0使用地址ChatGPT正确打开方式最新功能语音助手存档…

python222网站实战(SpringBoot+SpringSecurity+MybatisPlus+thymeleaf+layui)-帖子详情页实现

锋哥原创的SpringbootLayui python222网站实战: python222网站实战课程视频教程(SpringBootPython爬虫实战) ( 火爆连载更新中... )_哔哩哔哩_bilibilipython222网站实战课程视频教程(SpringBootPython爬虫实战) ( 火…

Python智能挖掘数据新秘器

大家好,本次分享一款在数据探索中表现出色的工具—Python Lux ,通过自动化可视化和数据分析过程,使得数据探索变得更加快捷方便。 Lux的使用方法非常简单,只需在Jupyter notebook中输入dataframe,Lux就会智能推荐一组基…

Java 设计者模式以及与Spring关系(三) 原型和适配器模式

简介: 本文是个系列一次会出两个设计者模式作用,如果有关联就三个,除此外还会讲解在spring中作用。 23设计者模式以及重点模式 我们都知道设计者模式有3类23种设计模式,标红是特别重要的设计者模式建议都会,而且熟读于心&#…

数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)二

第五部分、数组和广义表详解 数组和广义表,都用于存储逻辑关系为“一对一”的数据。 数组存储结构,99% 的编程语言都包含的存储结构,用于存储不可再分的单一数据;而广义表不同,它还可以存储子广义表。 本章重点从矩阵…

探秘网络爬虫的基本原理与实例应用

1. 基本原理 网络爬虫是一种用于自动化获取互联网信息的程序,其基本原理包括URL获取、HTTP请求、HTML解析、数据提取和数据存储等步骤。 URL获取: 确定需要访问的目标网页,通过人工指定、站点地图或之前的抓取结果获取URL。 HTTP请求&#…

行政快递管理软件使用教程

勤勤恳恳的行政人员,还在努力地修改企业快递管理制度,而聪明的行政人员,已经开始物色合适的快递管理软件了。随着企业管理的现代化发展,我们会发现很多管理模块都有相应的管理制度。人力资源管理、客户关系管理、财务管理等等&…

【LeetCode: 295. 数据流的中位数 + 堆】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

Python中如何简化if...else...语句

一、引言 我们通常在Python中采用if...else..语句对结果进行判断,根据条件来返回不同的结果,如下面的例子。这段代码是一个简单的Python代码片段,让用户输入姓名并将其赋值给变量user_input。我们能不能把这几行代码进行简化,优化…

beego API 自动化文档

API 全局设置 必须设置在 routers/router.go 中,文件的注释,最顶部: // APIVersion 1.0.0 // Title mobile API // Description mobile has every tool to get any job done, so codename for the new mobile APIs. // Contact astaxiegmai…

LLMs之Vanna:Vanna(利用自然语言查询数据库的SQL工具+底层基于RAG)的简介、安装、使用方法之详细攻略

LLMs之Vanna:Vanna(利用自然语言查询数据库的SQL工具底层基于RAG)的简介、安装、使用方法之详细攻略 目录 Vanna的简介 1、用户界面 2、RAG vs. Fine-Tuning 3、为什么选择Vanna? 4、扩展Vanna Vanna的安装和使用方法 1、安装 2、训练 (1)、使用…

Transformer|对图像数据构造patch序列+VIT整体架构解读(需进一步完善)

Attention在视觉的作用 使其关注到所值得关注的。 ViT(Vision transformer) 比如说图像是一个30x30x3的大小,可以将其拆分成9个10x10x3的部分,每个部分可以继续将10x10x3的部分拆解成300x1的向量来代表自己。(通常情…