Python进行threading多线程编程及高级并发处理机制

threading 模块是 Python 中用于进行多线程编程的标准库之一。通过 threading 模块,你可以创建和管理线程,使得程序能够并发执行多个任务。以下是一些基本的 threading 模块的用法:

1. 创建线程:

使用 threading.Thread 类可以创建一个新的线程。需要提供一个可调用对象(通常是一个函数),作为线程的执行体。

import threadingdef my_function():for _ in range(5):print("Hello from thread!")# 创建线程
my_thread = threading.Thread(target=my_function)# 启动线程
my_thread.start()# 主线程继续执行其他任务
for _ in range(5):print("Hello from main thread!")

2. 线程同步:

在多线程编程中,为了防止多个线程同时访问共享的资源,可以使用锁(threading.Lock)进行线程同步。

import threading# 共享资源
counter = 0
counter_lock = threading.Lock()def increment_counter():global counterfor _ in range(1000000):with counter_lock:counter += 1# 创建两个线程
thread1 = threading.Thread(target=increment_counter)
thread2 = threading.Thread(target=increment_counter)# 启动线程
thread1.start()
thread2.start()# 等待两个线程结束
thread1.join()
thread2.join()print("Counter:", counter)

3. 线程间通信:

在多线程编程中,线程之间可能需要进行通信。可以使用 threading.Eventqueue.Queue 等机制来实现线程间的通信。

使用 threading.Event
import threadingdef wait_for_event(event):print("Waiting for event to be set")event.wait()print("Event has been set")def set_event(event, delay):print(f"Waiting for {delay} seconds before setting the event")threading.Event().wait(delay)event.set()print("Event has been set")# 创建事件对象
event = threading.Event()# 创建两个线程
thread1 = threading.Thread(target=wait_for_event, args=(event,))
thread2 = threading.Thread(target=set_event, args=(event, 2))# 启动线程
thread1.start()
thread2.start()# 等待两个线程结束
thread1.join()
thread2.join()

 使用 queue.Queue

import threading
import queuedef producer(queue, items):for item in items:queue.put(item)def consumer(queue):while True:item = queue.get()if item is None:breakprint(f"Consumed: {item}")# 创建队列对象
my_queue = queue.Queue()# 创建两个线程
producer_thread = threading.Thread(target=producer, args=(my_queue, range(5)))
consumer_thread = threading.Thread(target=consumer, args=(my_queue,))# 启动线程
producer_thread.start()
consumer_thread.start()# 等待生产者线程结束
producer_thread.join()# 放置一个特殊值到队列中,表示消费者可以停止
my_queue.put(None)# 等待消费者线程结束
consumer_thread.join()

4.注意事项:

  • 尽量避免使用全局变量,或者确保在多线程操作时使用适当的同步机制(如锁)。
  • 谨慎使用共享资源,确保在多线程环境中正确管理资源。
  • 注意线程间的通信和同步,以防止数据竞争和死锁。

虽然 threading 模块提供了简单的多线程编程接口,但在一些场景中,使用 concurrent.futures 模块中的 ThreadPoolExecutorProcessPoolExecutor 类更加方便,它们提供了高级的并发处理机制。

concurrent.futures 模块提供了更高级的并发处理机制,其中的 ThreadPoolExecutorProcessPoolExecutor 类是两个常用的工具,分别用于线程池和进程池的并发执行。这两个类都是 concurrent.futures.Executor 的子类。

5.线程池ThreadPoolExecutor

ThreadPoolExecutor 提供了一个线程池,可以方便地在多个线程中执行函数。以下是一个简单的示例:

from concurrent.futures import ThreadPoolExecutor
import timedef my_function(message):time.sleep(2)return f"Hello, {message}!"# 创建线程池
with ThreadPoolExecutor(max_workers=3) as executor:# 提交任务并获取 Future 对象future1 = executor.submit(my_function, "Alice")future2 = executor.submit(my_function, "Bob")# 阻塞等待任务完成并获取结果result1 = future1.result()result2 = future2.result()print(result1)
print(result2)

上述代码中,ThreadPoolExecutor 创建了一个最大工作线程数为 3 的线程池,通过 submit 方法提交了两个任务,然后通过 result 方法获取任务的结果。

6.进程池ProcessPoolExecutor

ProcessPoolExecutor 提供了一个进程池,可以在多个进程中执行函数。同样是一个示例:

from concurrent.futures import ProcessPoolExecutor
import timedef my_function(message):time.sleep(2)return f"Hello, {message}!"# 创建进程池
with ProcessPoolExecutor(max_workers=3) as executor:# 提交任务并获取 Future 对象future1 = executor.submit(my_function, "Alice")future2 = executor.submit(my_function, "Bob")# 阻塞等待任务完成并获取结果result1 = future1.result()result2 = future2.result()print(result1)
print(result2)

这段代码与上一个示例类似,不同之处在于使用了 ProcessPoolExecutor 创建了一个进程池,任务在不同的进程中执行。这使得它适用于一些 CPU 密集型的任务,可以充分利用多核处理器的性能。

7.并发处理的优势:

  1. 简化并发编程: concurrent.futures 模块提供了更高层次的接口,简化了并发编程的复杂性。

  2. 易于管理任务: 使用 submit 方法可以方便地提交任务,并通过 Future 对象进行管理。

  3. 自动管理资源: 使用 with 语句创建 ThreadPoolExecutorProcessPoolExecutor 时,会自动管理资源的生命周期,不再需要手动管理线程或进程的启动和关闭。

  4. 可替代传统的 threadingmultiprocessing 模块: 在某些场景下,concurrent.futures 提供了更方便的方式来进行并发编程,特别是对于一些简单的并行任务。

在实际应用中,选择使用 concurrent.futures 模块还是传统的 threadingmultiprocessing 模块,取决于具体的需求和场景。如果你只是简单地执行一些任务,并发处理的复杂性较低,使用 concurrent.futures 可能更加方便。而对于更复杂的并发控制和线程/进程管理,传统的 threadingmultiprocessing 模块可能更适合。

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

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

相关文章

在两个java项目中实现Redis的发布订阅模式

如何在两个java项目中实现Redis的发布订阅模式? 1. Redis简介2. 发布订阅模式介绍3. 实现思路4. 代码实现及详细解释4.1. RedisUtil4.2. Publisher4.3. Subscriber4.4. 运行程序 目录: Redis简介发布订阅模式介绍实现思路代码实现及详细解释 1. Redis简…

HTB Napper WriteUp

Napper 2023年11月12日 14:58:35User Nmap ➜ Napper nmap -sCV -A -p- 10.10.11.240 --min-rate 10000 Starting Nmap 7.80 ( https://nmap.org ) at 2023-11-12 13:58 CST Nmap scan report for app.napper.htb (10.10.11.240) Host is up (0.15s latency). Not shown: …

gitee推荐-SAPI++

一下内容来自gitee。 SaaS-Apps-Engine: 智者|SAPI是多应用、多租户SaaS应用引擎,支持(小程序/公众号/轻应用/企微/抖音/支付宝/百度)等多平台应用。基于ThinkPHP6.1/8.0原生多应用模式开发,简洁、高效、易扩展。集成强大的权限控…

适用于电脑的5个免费文件恢复软件分享

适用于电脑的最佳免费文件恢复软件 任何计算机用户都可能经历过丢失重要文件的恐惧。重要数据的丢失可能会令人不安和沮丧,无论是由于不小心删除、计算机故障还是硬盘格式化造成的。幸运的是,在数字时代,您可以使用值得信赖的解决方案检索这些…

好工具|datamap,一个好用的地图可视化Excel插件,在Excel中实现地理编码、拾取坐标

在做VRP相关研究的时候,需要对地图数据做很多处理,比如地理编码,根据“重庆市沙坪坝区沙正街174号”这样的一个文本地址知道他的经纬度;再比如绘制一些散点图,根据某个位置的经纬度在地图上把它标注出来。还有有的时候…

vue + docxtemplater 导出 word 文档

一、痛点 word 导出 这种功能其实之前都是后端实现的,但最近有个项目没得后端。所以研究下前端导出。 ps: 前端还可以导出 pdf,但是其分页问题需要话精力去计算才可能实现,并且都不是很完善。可参考之前的文章:利用 h…

MIT6.824-Raft笔记:脑裂、Majority Vote(过半投票/过半选举)

本部分主要是问题引入,以及给出一个解决方案 1 脑裂(Split Brain) replication system的共同点:单点 前面几个容错特性(fault-tolerant)的系统,有一个共同的特点。 MapReduce复制了计算&…

JavaScript框架 Angular、React、Vue.js 的全栈解决方案比较

在 Web 开发领域,JavaScript 提供大量技术栈可供选择。其中最典型的三套组合,分别是 MERN、MEAN 和 MEVN。前端框架(React、Angular 和 Vue)进行简化比较。 MERN 技术栈详解 MERN 技术栈包含四大具体组件: MongoDB&am…

蓝桥杯物联网竞赛_STM32L071_3_Oled显示

地位: 对于任何一门编程语言的学习,print函数毫无疑问是一种最好的调试手段,调试者不仅能通过它获取程序变量的运行状态而且通过对其合理使用获取程序的运行流程,更能通过关键变量的输出帮你验证推理的正确与否,朴素的…

常见网络安全防护

1 阻断服务攻击(DOS) 阻断服务攻击,想办法目标网络资源用尽变种:分布式阻断服务攻击 影响: 宽带消耗性(消耗目标的带宽)资源消耗型(消耗目标的计算资源) 解决方案&am…

人工智能对网络安全的影响越来越大

如果问当前IT行业最热门的话题是什么,很少有人会回答除了人工智能(AI)之外的任何话题。 在不到 12 个月的时间里,人工智能已经从一项只有 IT 专业人员才能理解的技术发展成为从小学生到作家、程序员和艺术家的每个人都使用的工具…

MySQL索引事务基础

目录 1. 索引 1.1索引的概念 1.2索引的特点 1.3 索引的使用场景 1.4索引的使用 1.4.1查看索引 1.4.2创建索引 1.4.3删除索引 1.5索引保存的数据结构 2.事务 2.1经典例子 2.2事务的概念 2.3事务的使用 2.4事务的4个核心特性 2.5事务的并发问题 2.5.1脏读 2.5.2不可…

Python + Docker 还是 Rust + WebAssembly?

在不断发展的技术世界中,由大语言模型驱动的应用程序,通常被称为“LLM 应用”,已成为各种行业技术创新背后的驱动力。随着这些应用程序的普及,用户需求的大量涌入对底层基础设施的性能、安全性和可靠性提出了新的挑战。 Python 和…

Java项目如何打包成Jar(最简单)

最简单的办法,使用Maven插件(idea自带) 1.选择需要打包的mudule,点击idea右侧的maven插件 2.clean操作 3.选择需要的其他mudule,进行install操作(如果有) 4.再次选择需要打包的module&#…

Vue.observable 是什么

Observable 翻译过来我们可以理解成可观察的 Vue.js2.6 新增 Vue.observable,让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象 。 返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化…

Git的指令

Git 各平台安装包下载地址为:http://git-scm.com/downloads Ubuntu Git 安装命令为: $ apt-get install git用户信息 配置个人的用户名称和电子邮件地址: $ git config --global user.name "runoob" $ git config --global user.…

Python----类对象和实例对象

目录 一.类和类的实例 二.类属性和实例属性 三.私有属性和公有属性 四.静态方法和类方法 五.__init__方法,__new__方法和__del__方法: 六.私有方法和公有方法 七.方法的重载 八.方法的继承 九.方法的重写 十.对象的特殊方法 十一.对象的引用&a…

软件开发模式开源和闭源的优劣之争

开源和闭源,两种截然不同的开发模式,对于大模型的发展有着重要影响。开源让技术共享,吸引了众多人才加入,推动了大模的创新。而闭源则保护了商业利益和技术优势,为大模型的商业应用提供了更好的保障。 开源与闭源软件的…

基于命令行模式设计退款请求处理

前言 这篇文章的业务背景是基于我的另一篇文章: 对接苹果支付退款退单接口-CSDN博客 然后就是说设计模式是很开放的东西,可能我觉得合适,你可能觉得不合适,这里只是做下讨论,没有一定要各位同意的意思.... 相关图文件 这里我先把相关的图文件放上来,可能看着会比较清晰点 代码逻…

sql之left join、right join、inner join的区别

sql之left join、right join、inner join的区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录 inner join(等值连接) 只返回两个表中联结字段相等的行 举例如下&#xff1…