当前位置: 首页 > article >正文

python多线程+异步编程让你的程序运行更快

多线程简介

        多线程是Python中实现并发编程的重要方式之一,它允许程序在同一时间内执行多个任务。在某些环境中使用多线程可以加快我们代码的执行速度,例如我们通过爬虫获得了一个图片的url数组,但是如果我们一个一个存储很明显会非常缓慢,如果我们多创建几个线程执行这样我们的代码就会快上若干倍,同时在之前的实验中我们做了一个socket的聊天室如果它是单线程的话,就只能进行一问一答,于是我们创建了两个线程,一个线程用来监听对方的信息,另一个线程用来发送消息。

多线程编程

使用threading库创建线程并使用

接下来使用一个小代码来理解一下线程的概念。

from threading import Threaddef print_name(name):for i in range(100):print(f'name:{name},num:{i}')def main():t1 = Thread(target=print_name, args=('张三',))t2 = Thread(target=print_name, args=('李四',))t1.start()t2.start()t1.join()t2.join()if __name__ == '__main__':main()

        在代码中Thread类代表的是线程,我们定义了一个函数print_name作为任务,传入参数name代表名字,我们在函数中使用循环,让名字重复打印100次,同时显示第几次打印。在主函数中创建了两个线程t1和t2,再同时启动它们,join代表等待任务完成。

        在结果中我们发现,输出的张三和李四是掺杂在一起的,于是我们可以想象到它的执行过程应该是这样的:

                                                             t1   

          主进程                   ---------------------------------->

---------------------------->                                                 -------------------------------------->

                                        ---------------------------------->

                                                              t2  

        但是,我们思考一下,即使是输出乱套了,它依然是按照张三……李四……一条一条地执行print语句,输出数据的。而不是输出张李三四……的数据。

        这是因为在计算机中,打印资源为互斥资源,在访问的过程中需要互斥的访问,就是有的进程一旦占用了该资源,就必须等待它结束或者中断释放以后,别的进程才可以使用。

睡眠排序

        睡眠排序作为一种最没用的排序方式,虽然我们在实操的过程中根本就用不到这种方法。但是作为一个小练习,让我们对多线程的理解更加深刻,也是不错的。

from threading import Thread
import time
def act(num):time.sleep(num/10)print(num)def main():c = [5,4,2,9,8,7,6,1,3]for i in range(len(c)):t = Thread(target=act,args=(c[i],))t.start()
if __name__ == '__main__':    main()

        这个代码的思路是,把要排序的数组进行遍历,通过在循环中给每一个数值创建线程再执行。在线程中,规定先睡眠,根据传入的数字的大小决定谁先醒来,这样先醒来的线程就会先输出,所以先输出的就是较小的数。最后数字会按照从小到大的顺序输出。这种思路和传统的排序相比较它会把压力全部给到cpu。

线程池

from concurrent.futures import ThreadPoolExecutordef func(a):for i in range(10):print(a)
def main():with ThreadPoolExecutor(10) as t:t.submit(func,'1')t.submit(func,'2')t.submit(func,'3')t.submit(func,'4')t.submit(func,'5')t.submit(func,'6')if __name__ == '__main__':main()

        在ThreadPoolExecutor(10)中传入的参数是线程池中可以容纳的最大的线程的数量,这个数值和电脑的核数量有关,在一般情况下,推荐线程数 ≈ CPU核心数 + 1。

        至于电脑的cpu是几核的,可以通过下面的代码查看。

锁🔒

        锁(Lock)是多线程编程中最基本的同步机制,用于解决多线程环境下对共享资源访问的竞争问题,防止数据不一致的情况发生。多个线程同时访问/修改共享数据时,执行结果依赖于线程执行的顺序,如果进程之间有资源竞争的情况,那么就可能会造成资源的混乱。

        例如count+=1和读写文件的操作。

import threadingcounter = 0
lock = threading.Lock()def increment():global counterfor _ in range(100000):with lock:counter += 1threads = []
for _ in range(5):t = threading.Thread(target=increment)threads.append(t)t.start()for t in threads:t.join()print(f"counter: {counter}")

        但是在使用锁的过程中,一定要注意简单的锁不能重复使用,否则会导致进程无法被唤醒造成死锁。

异步编程介绍

        异步编程和多线程编程是现代软件开发中两种主要的并发处理方式,它们各有特点,适用于不同的场景。异步编程核心概念是任务发起后不必等待完成,可以继续执行其他操作,核心调度机制,管理所有异步任务的执行,所有任务在一个线程内交替执行,任务主动让出控制权。

使用async和await关键字

async

用于声明一个函数为异步函数(协程函数),被修饰的函数在被调用时会返回一个协程对象,而不是立即执行。

await

暂停当前协程的执行,等待一个可等待对象完成,非阻塞地等待。

import asyncioasync def fetch_data(n):print(f"开始获取数据{n}")await asyncio.sleep(2)print(f"数据获取完成{n}")async def main():task1 = asyncio.create_task(fetch_data(1))task2 = asyncio.create_task(fetch_data(2))await task1await task2asyncio.run(main())

        它的运行结果是

        在执行完task1的第一个打印后,有一个await关键字,到这里程序会暂时挂起当前的任务转而去执行其它的任务。

相关文章:

python多线程+异步编程让你的程序运行更快

多线程简介 多线程是Python中实现并发编程的重要方式之一,它允许程序在同一时间内执行多个任务。在某些环境中使用多线程可以加快我们代码的执行速度,例如我们通过爬虫获得了一个图片的url数组,但是如果我们一个一个存储很明显会非常缓慢&…...

各种场景的ARP攻击描述笔记(超详细)

1、ARP报文限速 上一章我们说过ARP报文也是需要上送CPU进行处理的协议报文,如果设备对收到的大量ARP报文全部进行处理,可能导致CPU负荷过重而无法处理其他业务。因此,在处理之前需要对ARP报文进行限速,以保护CPU资源。 1.根据源MAC地址或源IP地址进行ARP限速 当设备检测到某一…...

Java 实现 List<String> 与 String 互转

在 Java 开发过程中&#xff0c;有时需要将 List<String> 转为 String 存储&#xff0c;后续使用时再还原回去。此时就需要 Java 实现 List<String> 与 String 互转。以下是一种互转方式。 采用如下工具包实现。 <dependency><groupId>org.apache.com…...

庙算兵推:使用Streamlit框架构建了一个智能作战推演系统。

这段代码是一个完整的军事模拟应用&#xff0c;使用Streamlit框架构建了一个智能作战推演系统。该系统包括了三维地图显示、作战单位管理、应急事件处理等功能。用户可以通过界面控制推演的开始和暂停&#xff0c;调整时间加速倍率&#xff0c;并查看实时的战斗情况和系统状态。…...

daz3d ERC Freeze to Morph Target 和 另存为 Morph Asset(s)

. ERC 冻结至变形目标 (ERC Freeze to Morph Target) 核心目标&#xff1a;将骨架的调整与自定义造型的滑块关联起来。 详细解释&#xff1a; 当你创建一个自定义造型&#xff08;Morph&#xff09;并调整了骨架&#xff08;Rigging&#xff09;以适应这个新造型后&#xff…...

HDCP(四)

HDCP驱动开发实战深度解析 以下从协议栈架构、核心模块实现、安全设计到硬件集成&#xff0c;结合HDCP 2.x规范与主流硬件平台&#xff08;如ARM、FPGA&#xff09;特性&#xff0c;系统拆解驱动开发关键环节&#xff1a; 1. 协议栈架构与模块划分 驱动分层设计 硬件抽象层&…...

Docker MySQL的主从同步 数据备份 数据同步 配置文件

创建主库 docker run \--namemysql_1 \-e MYSQL_ROOT_PASSWORD123456 \-p 3306:3306 \-v mysql_main_data:/var/lib/mysql \--restart unless-stopped \-d \mysql:8.0进入容器内部 docker exec -it mysql_1 bash查找配置文件 find / -name my.cnf复制出主机 docker cp mysql…...

MATLAB在哪些特定领域比Python更有优势?

文章目录 前言科学研究与工程计算数值计算信号处理控制系统设计 教育领域易于学习和上手教学资源丰富 快速原型开发集成开发环境便捷 前言 MATLAB 在以下特定领域比 Python 更具优势&#xff1a; 科学研究与工程计算 数值计算 高效矩阵运算&#xff1a;MATLAB 以矩阵为基本数…...

linux安装mysql常出现的问题

wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm rpm -ivh mysql-community-release-el7-5.noarch.rpm yum update yum install mysql-server 权限设置&#xff1a; chown -R mysql:mysql /var/lib/mysql/ 初始化 MySQL&#xff1a; mysqld --initiali…...

C++手撕单链表及逆序打印

在学习数据结构的过程中&#xff0c;链表是一个非常重要的基础数据结构。今天&#xff0c;我们将通过C手动实现一个单链表&#xff0c;并添加一个逆序打印的功能&#xff0c;帮助大家更好地理解链表的实现和操作。 一、链表简介 链表是一种线性数据结构&#xff0c;其中每个元…...

996引擎-疑难杂症:Ctrl + F9 编辑好的UI进入游戏查看却是歪的

Ctrl F9 编辑好UI后&#xff0c;进入游戏查看却是歪的。 检查Ctrl F10 是否有做过编辑。可以找到对应界面执行【清空】...

JQuery初步学习

文章目录 一、前言二、概述2.1 介绍2.2 安装 三、语法3.1 文档就绪3.2 选择器 四、事件4.1 概述4.2 事件绑定/解绑4.3 一次性事件4.4 事件委托4.5 自定义事件 五、效果5.1 隐藏/显示5.2 淡入淡出5.3 滑动5.4 动画 六、链七、HTML7.1 内容/属性7.2 元素操作7.3 类属性7.4 样式属…...

repo仓库文件清理

1. repo 仓库内文件清理 # 清理所有Git仓库中的项目 repo forall -c git clean -dfx # 重置所有Git 仓库中的项目 repo forall -c git reset --hard 解释&#xff1a; repo forall -c git clean -dfx&#xff1a; repo forall 是一个用于在所有项目中执行命令的工具。-c 后…...

使用Docker部署Java项目的完整指南

前言 Docker是一个轻量级的容器化平台&#xff0c;可将应用及其依赖打包成标准化单元&#xff0c;实现快速部署和环境隔离。本文以Spring Boot项目为例&#xff0c;演示如何通过Dockerfile部署Java应用。 准备工作 本地环境 安装Docker Desktop&#xff08;官网下载&#xff0…...

基于 Spring Boot 瑞吉外卖系统开发(三)

基于 Spring Boot 瑞吉外卖系统开发&#xff08;三&#xff09; 分类列表 静态页面 实现功能所需要的接口 定义Mapper接口 Mapper public interface CategoryMapper extends BaseMapper<Category> {}定义Service接口 public interface CategoryService extends ISe…...

TCP,UDP协议和域名地址

1.TCP&#xff08;传输控制协议&#xff09;是面向连接&#xff0c;UDP&#xff08;用户数据报协议&#xff09;是无连接的 2.应用层&#xff1a;FTP,HTTP,SMTP,TELNET,DNS,TFTP 传输层;TCP,UDP 网际层&#xff1a;IP,ICMP,ARP,RARP 3.TCP21:20端口数据传输&#xff1b;21端…...

winserver2022备份

安装备份&#xff0c;然后等待安装完成即可 然后可以在这里看到安装好的win server2022备份 一直下一步然后到这里 不要用本地文件夹备份 备份到远程服务器&#xff0c;远程服务器路径 然后确定备份即可 如何恢复呢&#xff1f; 点击右侧的恢复就可以了 打开任务计划程序 这…...

GAT-GRAPH ATTENTION NETWORKS(论文笔记)

CCF等级&#xff1a;A 发布时间&#xff1a;2018年 代码位置 25年4月21日交 目录 一、简介 二、原理 1.注意力系数 2.归一化 3.特征组合与非线性变换 4.多头注意力 4.1特征拼接操作 4.2平均池化操作 三、实验性能 四、结论和未来工作 一、简介 图注意力网络&…...

SpringBoot和微服务学习记录Day1

分布式架构 为了解决大量的用户请求&#xff0c;需要多台服务器&#xff0c;为处理某些请求将一些服务器划分为一个集群&#xff0c;通过一种技术来处理集群的请求 典型应用&#xff1a; nginx&#xff1a;Tomcat集群 Redis&#xff1a;哨兵模式 MySQL&#xff1a;mycat 微…...

PDFBox/Itext5渲染生成pdf文档

目录 PDFBox最终效果实现代码 Itext5最终效果实现代码 PDFBox 使用PDFBox可以渲染生成pdf文档&#xff0c;并且自定义程度高&#xff0c;只是比较麻烦&#xff0c;pdf的内容位置都需要手动设置x&#xff08;横向&#xff09;和y&#xff08;纵向&#xff09;绝对位置&#xff…...

前端获取不到后端新加的字段 解决方案

前端获取不到后端新加的字段 解决方案 sql 返回的是 FileInfo 对象 private String lastUpdateTimeStr;// 自定义 setLastUpdateTime 方法&#xff0c;确保在设置 lastUpdateTime 时自动格式化为字符串public void setLastUpdateTime(LocalDateTime lastUpdateTime) {this.las…...

【Java学习】AI时代下如何学习Java语言开发

学习 Java 语言开发时&#xff0c;合理借助 AI 工具可以提升效率、深化理解&#xff0c;以下是具体的学习策略和方法&#xff1a; 一、利用 AI 辅助基础学习 1. 智能文档解读与语法解析 工具&#xff1a;ChatGPT、Bing Chat、Google Bard用法&#xff1a; 直接提问基础语法问…...

联想拯救者Y9000K重装Ubuntu系统

USB刻录Ubuntu&#xff0c;并插入电脑。 进入官网https://rufus.ie/downloads/&#xff0c;安装4.0p版本&#xff0c;对应Ubuntu 22.04版本进入官网https://www.releases.ubuntu.com/22.04/&#xff0c;下载Ubuntu 22.04的iso文件插入一个空USB。运行rufus.exe&#xff0c;选择…...

罗技K860键盘

罗技蓝牙键盘的顶部功能键F1-F12的原本功能 单击罗技键盘的功能键时&#xff0c;默认响应的是键盘上面显示的快进、调节音量等功能。改变回F1~F12原本功能&#xff0c;同时按下 fn和esc组合键...

PyTorch Tensor维度变换实战:view/squeeze/expand/repeat全解析

本文从图像数据处理、模型输入适配等实际场景出发&#xff0c;系统讲解PyTorch中view、squeeze、expand和repeat四大维度变换方法。通过代码演示对比不同方法的适用性&#xff0c;助您掌握数据维度调整的核心技巧。 一、基础维度操作方法 1. view&#xff1a;内存连续的形状重…...

【NLP 面经 9、逐层分解Transformer】

目录 一、Transformer 整体结构 1.Tranformer的整体结构 2.Transformer的工作流程 二、Transformer的输入 1.单词 Embedding 2.位置 Embedding 计算公式&#xff1a; 三、Self-Attention 自注意力机制 1.Self-Attention 结构 ​编辑 2.Q、K、V的计算 代码实现 3.Self-Attenti…...

【线程有哪些状态?这些状态如何相互转换?阻塞和等待的状态有什么区别?】

线程状态及其转换与区别 线程的生命周期包含多个状态&#xff0c;不同状态之间的转换由线程调度和同步机制决定。以下是线程状态的详细说明、转换关系及阻塞与等待的区别&#xff1a; 一、线程的六种基本状态&#xff08;以Java为例&#xff09; 状态描述NEW&#xff08;新建…...

netty中的ChannelPipeline详解

Netty中的ChannelPipeline是事件处理链的核心组件,负责将多个ChannelHandler组织成有序的责任链,实现网络事件(如数据读写、连接状态变化)的动态编排和传播。以下从核心机制、执行逻辑到应用场景进行详细解析: 1. 核心结构与组成 双向链表结构 组成单元:ChannelPipeline…...

Ubuntu 24.04 中文输入法安装

搜狗输入法&#xff0c;在Ubuntu 24.04上使用失败&#xff0c;安装教程如下 https://shurufa.sogou.com/linux/guide 出现问题的情况&#xff0c;是这个帖子里描述的&#xff1a; https://forum.ubuntu.org.cn/viewtopic.php?t493893 后面通过google拼音输入法解决了&#x…...

踩雷,前端一直卡在获取token中

问题&#xff1a;一直卡在var token SecureStorage.Default.GetAsync("auth_token").Result; public VideoService(){_httpClient new HttpClient();var token SecureStorage.Default.GetAsync("auth_token");} 这是一个典型的同步等待异步操作导致的死…...