Python多线程优化:提升程序性能的实例

更多Python学习内容:ipengtao.com

大家好,我是涛哥,今天为大家分享 Python多线程优化:提升程序性能的实例,全文5600字,阅读大约16钟。

多线程是一种有效的并发编程方式,能够提高程序的性能。本文将通过详细的实例代码,探讨如何优化Python多线程程序,以充分发挥多核处理器的潜力,提升程序的执行效率。

1. 多线程基础

首先,看一个简单的多线程示例,通过Python的threading模块创建两个线程并同时执行任务。

import threading
import timedef task1():for _ in range(5):print("Task 1")time.sleep(1)def task2():for _ in range(5):print("Task 2")time.sleep(1)if __name__ == "__main__":thread1 = threading.Thread(target=task1)thread2 = threading.Thread(target=task2)thread1.start()thread2.start()thread1.join()thread2.join()

2. 线程同步与互斥锁

在多线程环境中,为了避免竞争条件和保证数据一致性,需要使用互斥锁。以下是一个使用threading.Lock的例子:

import threadingcounter = 0
counter_lock = threading.Lock()def update_counter():global counterwith counter_lock:for _ in range(100000):counter += 1if __name__ == "__main__":thread1 = threading.Thread(target=update_counter)thread2 = threading.Thread(target=update_counter)thread1.start()thread2.start()thread1.join()thread2.join()print("Counter:", counter)

3. 线程池优化

使用线程池可以更好地管理线程的生命周期,减少线程的创建和销毁开销。以下是一个使用concurrent.futures.ThreadPoolExecutor的例子:

from concurrent.futures import ThreadPoolExecutor
import timedef task(num):print(f"Task {num} started")time.sleep(2)print(f"Task {num} completed")if __name__ == "__main__":with ThreadPoolExecutor(max_workers=3) as executor:for i in range(5):executor.submit(task, i)

4. 多线程与I/O密集型任务

对于I/O密集型任务,使用异步编程更为高效。以下是一个使用asyncio的例子:

import asyncioasync def task1():print("Task 1 started")await asyncio.sleep(2)print("Task 1 completed")async def task2():print("Task 2 started")await asyncio.sleep(2)print("Task 2 completed")if __name__ == "__main__":asyncio.run(asyncio.gather(task1(), task2()))

5. 避免全局解释器锁(GIL)

在CPython解释器中,全局解释器锁(GIL)限制了同一时刻只能有一个线程执行Python字节码。对于CPU密集型任务,可以考虑使用concurrent.futures.ProcessPoolExecutor,利用多进程来避免GIL。

from concurrent.futures import ProcessPoolExecutordef square(n):return n * nif __name__ == "__main__":with ProcessPoolExecutor() as executor:result = list(executor.map(square, [1, 2, 3, 4, 5]))print("Result:", result)

6. 线程安全的数据结构

在多线程环境中,选择线程安全的数据结构是至关重要的。以下是一个使用queue.Queue实现线程安全队列的例子:

import threading
import queue
import timedef producer(q):for i in range(5):time.sleep(1)item = f"Item {i}"print(f"Producing {item}")q.put(item)def consumer(q):while True:time.sleep(2)item = q.get()if item is None:breakprint(f"Consuming {item}")if __name__ == "__main__":my_queue = queue.Queue()producer_thread = threading.Thread(target=producer, args=(my_queue,))consumer_thread = threading.Thread(target=consumer, args=(my_queue,))producer_thread.start()consumer_thread.start()producer_thread.join()my_queue.put(None)  # Signal consumer to exitconsumer_thread.join()

7. 自定义线程池

有时候,可能需要更多的线程控制权,这时可以考虑实现自定义线程池。以下是一个简单的自定义线程池示例:

import threading
import queue
import timeclass CustomThreadPool:def __init__(self, max_workers):self.max_workers = max_workersself.work_queue = queue.Queue()self.workers = []def submit(self, func, args):self.work_queue.put((func, args))def worker(self):while True:func, args = self.work_queue.get()if func is None:breakfunc(*args)def start(self):for _ in range(self.max_workers):worker_thread = threading.Thread(target=self.worker)worker_thread.start()self.workers.append(worker_thread)def join(self):for _ in range(self.max_workers):self.work_queue.put((None, None))for worker_thread in self.workers:worker_thread.join()def task(num):print(f"Task {num} started")time.sleep(2)print(f"Task {num} completed")if __name__ == "__main__":custom_pool = CustomThreadPool(max_workers=3)for i in range(5):custom_pool.submit(task, (i,))custom_pool.start()custom_pool.join()

8. 使用threading.Event进行线程间通信

在多线程编程中,线程间通信是一个重要的话题。使用threading.Event可以实现简单而有效的线程间通信。以下是一个示例:

import threading
import timedef worker(event, thread_num):print(f"Thread {thread_num} waiting for event.")event.wait()  # 等待事件被设置print(f"Thread {thread_num} received the event.")if __name__ == "__main__":event = threading.Event()threads = []for i in range(3):thread = threading.Thread(target=worker, args=(event, i))threads.append(thread)thread.start()print("Main thread sleeping for 2 seconds.")time.sleep(2)event.set()  # 设置事件,通知所有等待的线程for thread in threads:thread.join()

9. 使用threading.Condition进行复杂线程同步

在某些情况下,需要更复杂的线程同步机制。threading.Condition提供了这样的功能,以下是一个生产者-消费者问题的示例:

import threading
import timeMAX_BUFFER_SIZE = 3
buffer = []
buffer_lock = threading.Lock()
buffer_not_full = threading.Condition(lock=buffer_lock)
buffer_not_empty = threading.Condition(lock=buffer_lock)def producer():global bufferfor i in range(5):time.sleep(1)with buffer_not_full:while len(buffer) == MAX_BUFFER_SIZE:buffer_not_full.wait()  # 缓冲区已满,等待通知buffer.append(i)print(f"Produced {i}")buffer_not_empty.notify()  # 通知消费者缓冲区非空def consumer():global bufferfor i in range(5):time.sleep(2)with buffer_not_empty:while not buffer:buffer_not_empty.wait()  # 缓冲区为空,等待通知item = buffer.pop(0)print(f"Consumed {item}")buffer_not_full.notify()  # 通知生产者缓冲区未满if __name__ == "__main__":producer_thread = threading.Thread(target=producer)consumer_thread = threading.Thread(target=consumer)producer_thread.start()consumer_thread.start()producer_thread.join()consumer_thread.join()

10. 使用threading.Timer进行定时任务

threading.Timer可以用于执行定时任务,以下是一个简单的定时任务的示例:

import threadingdef print_hello():print("Hello, Timer!")if __name__ == "__main__":timer = threading.Timer(5, print_hello)  # 5秒后执行print_hello函数timer.start()timer.join()

总结

通过本文,深入探讨了Python中多线程编程的各个方面,并提供了丰富的示例代码来演示不同的技术和最佳实践。在多线程编程中,学习如何创建和启动线程,处理线程间通信,使用线程锁进行同步,以及通过队列实现线程安全的数据交换。还深入了解了线程池的概念和实现,展示了如何自定义线程池以及处理线程池中的任务。进一步地,介绍了线程间通信的不同方式,包括使用threading.Event进行简单通信和使用threading.Condition进行复杂的线程同步。还演示了如何利用threading.Timer实现定时任务,以及在多线程环境中的异常处理和安全性考虑。

通过这些例子,可以更全面地理解和应用多线程编程,更好地解决实际问题,并提高Python程序的效率。在设计和优化多线程程序时,根据具体需求选择适当的线程同步机制和通信方式是至关重要的。

如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

更多Python学习内容:ipengtao.com

干货笔记整理

  100个爬虫常见问题.pdf ,太全了!

Python 自动化运维 100个常见问题.pdf

Python Web 开发常见的100个问题.pdf

124个Python案例,完整源代码!

PYTHON 3.10中文版官方文档

耗时三个月整理的《Python之路2.0.pdf》开放下载

最经典的编程教材《Think Python》开源中文版.PDF下载

点击“阅读原文”,获取更多学习内容

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

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

相关文章

(六)基于高尔夫优化算法GOA求解无人机三维路径规划研究(MATLAB代码)

一、无人机模型简介: 单个无人机三维路径规划问题及其建模_IT猿手的博客-CSDN博客 参考文献: [1]胡观凯,钟建华,李永正,黎万洪.基于IPSO-GA算法的无人机三维路径规划[J].现代电子技术,2023,46(07):115-120 二、高尔夫优化算法GOA简介 高尔夫优化算法…

c++——取地址(引用)和取内容(解引用)操作

今天又做蒙了一道题,把思考和实验记录下来。 struct sk{ int a; float b;}data; int *p; 若要使p指向data中的a域,正确的赋值语句是 p&a; pdata.a; p&data.a; *pdata.a前两个可以很容易看出错误之处,a是结构体内的变量,需…

P0级事故频发后,这家公司终于醒悟了!

近期,国内的互联网大厂接连爆发P0级事件,阿里云崩完滴滴崩,企业在追求效益的前提是业务的连续和稳定。如果发生故障不能快速恢复,引发业务中断,给企业带来的损失是巨大的,换言之,企业需要一套清…

OFDM通信连路仿真学习

文章目录 前言一、前置知识1、块状导频与梳状导频①、相似点②、区别③、其他 2、其他知识 二、仿真任务及方案1、仿真任务2、仿真方案 三、MATLAB仿真1、MATLAB 源码2、程序流程3、仿真结果①、打印信息③、8PSK 星座图②、脉冲成型图③、ETU300登加AWGN信道下误比特率曲线 四…

Windows系统搭建Appium 2 和 Appium Inspector 环境

前言 自 2022 年 1 月 1 日起,Appium 核心团队不再维护 Appium 1.x。官方支持的平台驱动程序的所有最新版本均不兼容 Appium 1.x,需要 Appium 2 才能运行。 Appium 2是一个自动化移动应用程序的开源工具,它带来了以下重要改进:  …

PowerDesigner数据库建模软件的安装

解压: 解压好以后,点击PowerDesigner.exe安装 这个安装的版本是15 选择安装路径,可以默认可以自定义: 直接点next: 全选了 点击next: 点击next: 点finish 汉化: 先把pojie和汉化文件…

Redis:主从复制

目录 概念配置步骤通过命令配置主从复制原理薪火相传反客为主哨兵(Sentinel)模式原理配置SpringBoot整合Sentinel模式 概念 主机更新后根据配置和策略,自动同步到备机的master/slave机制,Master以写为主,Slave以读为主。 作用: …

JVM 字节码

JVM概述 问题引出 你是否也遇到过这些问题? 运行着的线上系统突然卡死,系统无法访问,甚至直接OOM!想解决线上JVM GC问题,但却无从下手。新项目上线,对各种JVM参数设置一脸茫然,直接默认吧&…

ssm的鲜花销售系统(有报告)。Javaee项目。

演示视频: ssm的鲜花销售系统(有报告)。Javaee项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring SpringMvc Mybatis…

python用YOLOv8对图片进行分类

用yolov8的模型进行分类 先上效果图 图片资源 模型下载地址 https://github.com/ultralytics/ultralytics 代码 import matplotlib.pyplot as plt from ultralytics import YOLO from PIL import Image import cv2model YOLO(../ultralytics/yolov8n.pt)# print(model…

一款好用的windows窗口置顶工具

常用的windows窗口置顶工具如下,但是实际操作下来都不太好用或者有时不生效,导致窗口无法置顶,工作效率低频。 DeskPins 是一个允许用户将任何窗口(包括顶级窗口和对话框)置顶于桌面的工具。如果你正在寻找类似 DeskPi…

innovus如何检查missing via

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 verifyConnectivity innovus检查绕线的missing via可以使用verifyConnectivity命令,如果有net routing missing via问题,会报告pieces of net are not …

C语言——指针(三)

📝前言: 上篇文章C语言——指针(二)中对:指针的运算和指针变量类型对指针使用的影响开展了进一步的探讨,这篇文章我们继续学习一下指针与一维数组之间的关系: 1,对数组名的理解 2&am…

MySQL5.7下载安装教程

Mysql5.7下载地址:https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-winx64.zip 特别说明: 如果安装过程中出错可以卸载重装。具体步骤: 1、先在控制面板下载所有带MySQL的软件。 2、删除相关文件夹,可以使用Every…

python + mongodb使用入门

最近用了下mongodb ,简单做个记录: 1.启动系统mongo服务 mongod -f mongod.conf其中 mongod.conf 是配置文件,示例如下: dbpath/youpath/data/db #数据库保存位置 logpath/youpath/data/mongod.log #日志 logappendtrue fo…

突发,合肥一废品回收站发生火灾,富维AI神器助力防灾

昨晚,合肥一废品回收站突发火灾,火光冲天,烟雾蔓延。幸亏及时发现,消防人员迅速到场,控制了火势。这起事件让我们再次认识到火灾报警的重要性。而在这方面,北京富维图像公司的FIS智能图像识别系统就发挥了巨…

#HarmonyOS:软件安装

软件地址 https://developer.harmonyos.com/cn/develop/deveco-studio#download 安装的建议 这个界面这样选,其他界面全部按照默认路径往下走!!! 等待安装… 安装环境错误处理 一般就是本地node配置一场导致,建议…

springboot 中通过定时任务备份数据库并压缩传输到指定另外一台linux服务器得文件夹中 或 发送压缩包到指定邮箱

1、将JSch和邮件插件添加到项目pom文件中。Maven <!--java 通过JSch操作Linux--> <dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version> </dependency><!-- 邮件模板…

ElementPlusError: [ElPagination] 你使用了一些已被废弃的用法,请参考 el-pagination 的官方文档

使用element table出现这个错误好几回了&#xff0c;今天把它记录一下&#xff0c;并把错误原因复盘一遍。具体如下&#xff1a; 错误截图 原因 其实这个错误挺迷的&#xff0c;我把各种情况都测试了一遍&#xff0c;最后发现是因为给 翻页参数 total 传值错误导致的。 总结…

实时沟通,实时增长:企业使用WhatsApp Business的不二选择

在数字化浪潮中&#xff0c;WhatsApp Business崭露头角&#xff0c;成为企业与客户之间沟通的新利器。今天运营坛将和大家深入探讨WhatsApp Business在2023年为企业带来的机遇&#xff0c;从增长率、客户群体、功能特性以及优势等方面剖析为何企业需要充分利用这一强大工具。 W…