并发编程-线程
并发编程-线程
- 一个进程是操作系统中运行的一个任务,进程独立拥有CPU、内存等资源
- 一个线程是一个进程中运行的一个任务,线程之间共享CPU、内存等资源,进程里的每一个任务都是线程。
线程创建
创建线程:使用threading模块中的Thread类来创建线程
- target表示线程执行的任务
- args表示任务的参数,是一个元组
- start()方法指启动线程
- join()方法指等待线程结束
from threading import Threaddef task(count:int):...thread1 = Thread(target=task, args=(10,)) # 创建子线程thread1
thread1.start() # 启动子线程
启动两个线程执行task任务
from threading import Threaddef task(count: int):for i in range(count):print(i)thread1 = Thread(target=task, args=(10,))
thread2 = Thread(target=task, args=(20,))thread1.start() # 启动线程1
thread2.start() # 启动线程2
print("main thread is end") # 执行到此处,主线程无任务,自行结束
输出结果:
0
1
2
3
4
5
06main thread is end78
9
1
2
3
4
5
6
7
8
9
等待主线程结束:
from threading import Threaddef task():for i in range(10):print(i)thread1 = Thread(target=task)
thread2 = Thread(target=task)thread1.start()
thread2.start()
thread1.join() # 等待线程执行结束
thread2.join() # 等待线程执行结束
print("main thread is end") # 等到线程1和线程2任务执行完毕,主线程才会结束
输出结果:
0
1
2
3
4
50
6
7
8
9
12
3
4
5
6
7
8
9
main thread is end
通过继承创建线程
通过继承Thread类来创建线程
打印混乱的原因:多线程执行时,print函数打印内容后会再打印换行,导致换行来不及打印,出现打印混乱
解决办法:行尾手动加换行,print函数end参数设置为空字符串
print(f"{self.name} - {i}\n", end="")
from threading import Threadclass MyThread(Thread):def run(self) -> None:# 线程的任务脚本pass
import time
from threading import Threadclass MyThread(Thread):def __init__(self, name: str, count: int):super().__init__()# 该方法已弃用,使用name属性替换# self.setName()self.name = name # 设置线程名称self.count = countdef run(self) -> None:# 线程的任务脚本for i in range(self.count):print(f"{self.name} - {i}\n", end="")# 休眠10毫秒time.sleep(0.01)t1 = MyThread("a", 10)
t2 = MyThread("b", 10)
t1.start()
t2.start()
输出结果:
D:\Python3.11\python.exe F:/Code/python_code/high_python/python_advance/thread/demo01_class.py
a - 0
b - 0
a - 1
b - 1
b - 2
a - 2
a - 3
b - 3
b - 4
a - 4
b - 5
a - 5
b - 6
a - 6
b - 7
a - 7
b - 8
a - 8
b - 9
a - 9
守护线程
主线程结束,守护线程会自动结束,这就叫守护线程
- 守护线程会在主线程结束时候自动结束
- 主线程则需要等待到所有的非守护线程结束才能结束
- 守护线程一般用于非关键性的线程,比如:日志
from threading import Threaddef task():for i in range(10):print(i)thread = Thread(target=task, daemon=True)
thread.start()
输出结果:
0
Process finished with exit code 0
等待线程结束
from threading import Threaddef task():for i in range(10):print(i)thread = Thread(target=task, daemon=True)
thread.start()
thread.join()
输出结果:
D:\Python3.11\python.exe F:/Code/python_code/high_python/python_advance/thread/demo03_daemon_thread.py
0
1
2
3
4
5
6
7
8
9Process finished with exit code 0
继承类设置守护线程
class MyThread(Thread):def __init__(self, name: str, count: int):super().__init__()# 该方法已弃用,使用name属性替换# self.setName()self.name = name # 设置线程名称self.count = countself.daemon = Truedef run(self) -> None:# 线程的任务脚本for i in range(self.count):print(f"{self.name} - {i}\n", end="")# 休眠10毫秒time.sleep(0.01)t1 = MyThread("a", 10)
t2 = MyThread("b", 10)
t1.start()
t2.start()
t1.join() # 等待t1结束,结束主线程
线程安全队列
queue模块中的Queue类提供了线程安全队列功能
- put(item, block=False) # 队列元素满时,不阻塞,会抛出异常,为True时,会让线程阻塞等待, 可能会导致线程卡死
- put(item, timeout=3) # 队列元素满时,等待timeout时间,如果超出时间则抛出异常
- get(block=False) # 从队列取元素,如果队列为空则不阻塞,会抛出异常
- get(timeout=10) # 从队列取元素,如果队列为空则则赛等待10秒,超时抛出异常
- qsize() # 队列大小
- empty() # 判断队列是否为空
- full() # 判断队列是否满的
生产者消费者线程实例
from threading import Thread
from queue import Queueclass Producer(Thread):"""生产者"""def __init__(self, name: str, count: int, queue: Queue) -> None:super(Producer, self).__init__()# 线程自带属性self.name = name# 自定义属性self.count = countself.queue = queuedef run(self) -> None:for n in range(self.count):msg = f"{self.name} - {n}"self.queue.put(msg, block=True)class Consumer(Thread):"""消费者"""def __init__(self, name: str, queue: Queue) -> None:super().__init__()self.name = nameself.daemon = Trueself.queue = queuedef run(self) -> None:while True:msg = self.queue.get(block=True)print(f"{self.name} - {msg}\n", end="")queue = Queue(maxsize=3)
threads = [Producer("p1", 10, queue),Producer("p2", 10, queue),Producer("p3", 10, queue),Consumer("c1", queue),Consumer("c2", queue),
]for t in threads:t.start()
线程池
- 线程的创建和销毁相对比较耗费资源
- 频繁的创建和销毁线程不利于高性能
- 线程池是python提供的便于线程管理和提高性能的工具
python提供两个类来管理线程
concurrent.futures.ThreadPoolExecutor- submit() # 启动/执行一个任务,返回结果是一个Future对象
- map() # 多个任务执行,将不同参数分配到每一个任务中
- shutdown() # 关闭线程池
- Future
- result() # 任务执行结果
- exception() # 任务异常信息
方式一:适用于不同任务
from concurrent.futures import ThreadPoolExecutor
import timedef task(name: str):print(f"{name} - step 1\n", end="")time.sleep(1)print(f"{name} - step 2\n", end="")return f"{name} complete"with ThreadPoolExecutor() as executor:result_1 = executor.submit(task, "A")result_2 = executor.submit(task, "B")print(result_1.result()) # result()会等待有结果再返回print(result_2.result())"""
A - step 1
B - step 1
A - step 2
A complete
B - step 2
B complete
"""
方式二:map()适用于同一任务,不同参数
from concurrent.futures import ThreadPoolExecutor
import timedef task(name: str) -> str:print(f"{name} - step 1\n", end="")time.sleep(1)print(f"{name} - step 2\n", end="")return f"{name} complete"with ThreadPoolExecutor() as executor:results = executor.map(task, ["C", "D"])for r in results:print(r)"""
C - step 1
D - step 1
D - step 2
C - step 2
C complete
D complete
"""
多线程案例:下载图片
from concurrent.futures import ThreadPoolExecutor
from urllib.request import urlopen, Request
import osdef download_img(url: str):site_url = Request(url, headers={})with urlopen(site_url) as web_file:img_data = web_file.read()if not img_data:raise Exception(f"Error: can not load the image from {url}")file_name = os.path.basename(url)with open(file_name, "wb") as f:f.write(img_data)return "Download image successfully, {}".format(url)urls = ["https://img0.bdstatic.com/static/searchresult/img/baseimg3_4f26a23.png",# "..."
]
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36","content-type": "Content-Type: image/jpeg"
}
with ThreadPoolExecutor() as ececutor:results = ececutor.map(download_img, urls)for r in results:print(r)
执行结果:
PS F:\Code\python_code\high_python\python_advance\thread> python .\thread_pool_demo.py
Download image successfully, https://img0.bdstatic.com/static/searchresult/img/baseimg3_4f26a23.png
相关文章:
并发编程-线程
并发编程-线程 一个进程是操作系统中运行的一个任务,进程独立拥有CPU、内存等资源一个线程是一个进程中运行的一个任务,线程之间共享CPU、内存等资源,进程里的每一个任务都是线程。 线程创建 创建线程:使用threading模块中的Th…...
图解LeetCode——剑指 Offer 34. 二叉树中和为某一值的路径
一、题目 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。叶子节点 是指没有子节点的节点。 二、示例 2.1> 示例 1: 【输入】root [5,4,8,11,null,13,4,7,2,null,null,5,1], t…...
使用Python免费试用最新Openai API
一、背景介绍 3月2日凌晨,OpenAI放出了真正的ChatGPT API,不是背后的GPT-3.5大模型,是ChatGPT的本体模型!ChatGPT API价格为1k tokens/$0.002,等于每输出100万个单词,价格才2.7美金(约18元人民…...
04、启动 SVN 服务器端程序
启动 SVN 服务器端程序1 概述2 用命令行单项目启动2.1 采用 svnserve 命令2.2 验证服务是否启动2.3 命令行方式的缺陷3 注册Windows服务3.1 注册服务的命令3.2 命令说明3.3 启动服务1 概述 SVN 服务器和 Tomcat 服务器,Nexus 服务器一样, 必须处于运行状态才能响应…...
jsp船舶引航计费网站Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 JSP船舶引航计费网站是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0&…...
Allegro如何画半圆形的线操作指导
Allegro如何画半圆形的线操作指导 在用Allegro设计PCB的时候,在某些应用场合会需要画半圆形,如下图 如何画半圆形,具体操作如下 点击Add点击Arc w/Radius...
【强烈建议收藏:MySQL面试必问系列之SQL语句执行专题】
一.知识回顾 之前的文章我们一起学习了MySQL面试必问系列之事务专题、锁专题,没有学习的小伙伴可以直接通过该链接地址直接访问,MYSQL你真的了解吗专栏的文章,接下来我们就一起来学习一下MySQL中SQL语句的执行流程,看看你掌握的怎…...
详解Linux下的环境变量以及C++库文件和头文件、python库的配置
目录 Linux环境变量配置基本步骤 1.查看环境变量 2.设置环境变量 3.永久性设置环境变量 4.使用环境变量 C 库文件和头文件环境变量配置 1.配置so库文件的环境变量 2.配置头文件的环境变量 Python库环境变量配置 Linux配置执行文件环境变量 我们都习惯在Windows 上配置…...
企业级分布式数据库 - GaussDB介绍
目录 什么是GaussDB 简介 应用场景 产品架构 产品优势 安全 责任共担 身份认证与访问控制 数据保护技术 审计与日志 监控安全风险 故障恢复 认证证书 GaussDB与其他服务的关系 约束与限制 计费模式 什么是GaussDB …...
Linux I2C 驱动实验
目录 一、Linux I2C 驱动简介 1、I2C 总线驱动 2、I2C 设备驱动 1、 i2c_client 结构体 2、 i2c_driver 结构体 二、硬件分析 三、设备树编写 1、pinctrl_i2c1 2、在 i2c1 节点追加 ap3216c 子节点 3、验证 四、 代码编写 1、makefile 2、ap3216c.h 3、ap3216c.c …...
DC-DC模块电源隔离直流升压高压稳压输出5v12v24v转60v100v110v150v220v250v300v400v500v
特点效率高达80%以上1*1英寸标准封装单电压输出稳压输出工作温度: -40℃~85℃阻燃封装,满足UL94-V0 要求温度特性好可直接焊在PCB 上应用HRB 0.2~10W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为:4.5~9V、9~18V、及18~36VDC标准&#…...
EF有几种模式,EF的三种模式分别是什么?
EF有几种模式,EF的三种模式分别是什么? 第一种:DataBase First DataBase First传统的表驱动方式创建EDM,然后通过EDM生成模型和数据层代码。除生成实体模型和自跟踪实现模型,还支持生成轻型DbContext。 解释…...
数据可视化展示:打工人常见职业病,颈腰椎病占比最高达66.51%
身体健康才是一切的根本。只有身体健健康康才能更好的去享受世间的美好,无论是谁都应当注重身体健康,而不是无度的挥霍它! 良好的身体,释放给工作,健壮的体魄,享受美好生活,良好的心态ÿ…...
【食品图像识别】Large Scale Visual Food Recognition
1 引言 视觉智能部与中科院计算所于2020-2021年度展开了《细粒度菜品图像识别和检索》科研课题合作,本文系双方联合在IEEE T-PAMI2023发布论文《Large Scale Visual Food Recognition》 (Weiqing Min, Zhiling Wang, Yuxin Liu, Mengjiang Luo, Liping Kang, Xiaom…...
RAN-in-the-Cloud:为 5G RAN 提供云经济性
RAN-in-the-Cloud:为 5G RAN 提供云经济性 5G 部署在全球范围内一直在加速。 许多电信运营商已经推出了5G服务并正在快速扩张。 除了电信运营商之外,企业也对使用 5G 建立私有网络产生了浓厚的兴趣,这些私有网络利用了更高的带宽、更低的延迟…...
vector、list、queue
引用:windows程序员面试指南 vector vector 类似于C语言中的数组 vector 支持随机访问,访问某个元素的时间复杂度 O(1) vector 插入和删除元素效率较低,时间复杂度O(n) vector 是连续存储,没有内存碎片,空间利用率高…...
操作系统面经
进程与线程区别 1.进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位) 2.进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数…...
一天约了4个面试,复盘一下面试题和薪资福利
除了最新的面经分享,还有字节大佬的求职面试答疑,告诉你关键问题是什么?少走弯路。**另外本文也汇总了6份大厂面试题:字节、腾讯、小米、腾讯云、滴滴、小米游戏。**希望对大家有帮助。 前言 昨天我的交流群里,有位宝…...
详解单链表(内有精美图示哦)
全文目录引言链表链表的定义与结构链表的分类单链表的实现及对数据的操作单链表的创建与销毁创建销毁单链表的打印单链表的头插与头删头插头删单链表的尾插与尾删尾插尾删单链表的查找单链表在pos位置后插入/删除插入删除单链表在pos位置插入/删除插入删除总结引言 在上一篇文…...
csdn文章导航
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
