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

更多Python学习内容:ipengtao.com

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

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

1. 多线程基础

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

import threading
import time

def 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 threading

counter = 0
counter_lock = threading.Lock()

def update_counter():
    global counter
    with counter_lock:
        for _ in range(100000):
            counter += 1

if __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 time

def 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 asyncio

async 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 ProcessPoolExecutor

def square(n):
    return n * n

if __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 time

def 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:
            break
        print(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 exit
    consumer_thread.join()

7. 自定义线程池

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

import threading
import queue
import time

class CustomThreadPool:
    def __init__(self, max_workers):
        self.max_workers = max_workers
        self.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:
                break
            func(*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 time

def 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 time

MAX_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 buffer
    for 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 buffer
    for 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 threading

def 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下载

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

交叉编译

1. 交叉开发 交叉编译: 在电脑把程序编写 编译 调试好 再下载到嵌入式产品中运行 编译: gcc 之前编译环境和运行环境是一样的 交叉编译: 编译 把编译代码和运行分开 编译代码在虚拟机中 运行…

WebGL笔记:图形旋转的原理和实现

旋转 1 )旋转的概念 三维物体的旋转要比位移复杂一点,三维物体的旋转需要满足以下条件: 旋转轴旋转方向旋转角度 场景举例 模型站在旋转轴的起点进行旋转模型要往左转还是往右转,就是旋转的方向模型旋转的大小就是旋转角度 2 &…

基于SpringBoot的公益慈善平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: 基于SpringBoot的公益…

使用Python实现SVM来解决二分类问题

下面是一个使用Python实现SVM来解决二分类问题的例子: # 导入所需的库 from sklearn.datasets import make_blobs from sklearn.model_selection import train_test_split from sklearn.svm import SVC import matplotlib.pyplot as plt# 生成一个二分类数据集 X, …

ESP32-Web-Server 实战编程-通过网页控制设备多个 GPIO

ESP32-Web-Server 实战编程-通过网页控制设备多个 GPIO 概述 上节 ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO 讲述了如何通过网页控制一个 GPIO。本节实现在网页上控制多个 GPIO。 示例解析 前端设计 前端代码建立了四个 GPIO,如下死 GPIO 2 在前端的…

STM32F407-14.3.5-01捕获_比较通道

捕获/比较通道 每一个捕获/比较通道都是围绕着一个捕获/比较寄存器(包含影子寄存器) 包括: 捕获的输入部分(数字滤波、多路复用和预分频器), 输出部分(比较器和输出控制)。 中文参考手册中框图分成了三大模块, 把框图合并成了一个整体,以便更好的理解捕获输…

深度学习之基于百度飞桨PaddleOCR图像字符检测识别系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介主要特点使用步骤 二、功能三、系统四. 总结 一项目简介 # Introduction to PaddleOCR Image Character Detection and Recognition System Based on Baidu…

Java---权限修饰符、final、static

文章目录 1. 权限修饰符2. final(最终态)3. static(静态) 1. 权限修饰符 修饰符同一个类中同一个包中的子类和无关类不同包的子类不同包的无关类private√默认√√protected√√√public√√√√ 2. final(最终态) 1. final关键字是最终的意思,可以修饰成员方法、…

Appium PO模式UI自动化测试框架——设计与实践

1. 目的 相信做过测试的同学都听说过自动化测试,而UI自动化无论何时对测试来说都是比较吸引人的存在。相较于接口自动化来说,它可以最大程度的模拟真实用户的日常操作与特定业务场景的模拟,那么存在即合理,自动化UI测试自然也是广…

《融合SCADA系统数据的天然气管道泄漏多源感知技术研究》误报数据识别模型开发

数据处理不作表述。因为我用的是处理后的数据,数据点这。 文章目录 工作内容1CC040VFD电流VFD转速压缩机转速反馈进出口差压 紧急截断阀开到位进出电动阀开到位发球筒电筒阀开到位收球筒电动阀开到位电动阀2005开到位越站阀开到位 工作内容2工作内容3 工作内容1 任…

金字塔原理 读书笔记

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言第1篇 表达的逻辑第1章 为什么要用金字塔结构归类分组,将思想组织成金字塔自上而下表达,结论先行自下而上思考,总结概括 第2…

Spark---资源、任务调度

一、Spark资源调度源码 1、Spark资源调度源码过程 Spark资源调度源码是在Driver启动之后注册Application完成后开始的。Spark资源调度主要就是Spark集群如何给当前提交的Spark application在Worker资源节点上划分资源。Spark资源调度源码在Master.scala类中的schedule()中进行…

基于SSM的云鑫曦科技办公自动化管理系统设计与实现

基于SSM的云鑫曦科技办公自动化管理系统设计与实现 摘 要: 随着时代的发展,单位办公方式逐渐从传统的线下纸张办公转向了使用个人pc的线上办公,办公效率低下的传统纸质化办公时代的淘汰,转型到信息化办公时代,面对当今数据逐渐膨…

奇数求和(C++)

系列文章目录 进阶的卡莎C++_睡觉觉觉得的博客-CSDN博客数1的个数_睡觉觉觉得的博客-CSDN博客双精度浮点数的输入输出_睡觉觉觉得的博客-CSDN博客足球联赛积分_睡觉觉觉得的博客-CSDN博客大减价(一级)_睡觉觉觉得的博客-CSDN博客小写字母的判断_睡觉觉觉得的博客-CSDN博客纸币(…

Keil5 debug

目录 debug调试功能 基本功能: 程序复位:Reset 运行:Run 停止:Stop 断点调试(Breakpoint Debugging) 单步调试: 单步调试:Step 单步跳过调试:Step Over: 单步返…

vue项目中使用jsonp跨域请求百度联想接口

一. 内容简介 vue项目中使用jsonp跨域请求百度联想接口 二. 软件环境 2.1 Visual Studio Code 1.75.0 2.2 chrome浏览器 2.3 node v18.14.0 三.主要流程 3.1 代码 核心代码 // 这个是请求函数doLeno() {// 挂载回调函数,不挂载,会报不存在window…

算法中的时间复杂度,空间复杂度

一、前言 算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别 衡量不同算法之间的优劣主要是通过时…

【动态规划】求最长递增子序列问题

目录 问题描述递推关系建立递推关系的思路约束条件:以 s [ k ] s[k] s[k] 结尾约束条件:以 s [ k ] s[k] s[k] 开头约束条件:增加子问题参数(前缀)约束条件:增加子问题参数(后缀)约束条件:LIS长度为k且末尾元素最小 运行实例 问…

MySQL -DDL 及表类型

DDL 创建数据库 CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...] create_specification:[DEFAULT] CHARACTER SET charset_name [DEFAULT] COLLATE collation_name 1.CHARACTER SET&#xff1a…

Java后端开发——MVC商品管理程序

Java后端开发——MVC商品管理程序 本篇文章内容主要有下面几个部分: MVC架构介绍项目环境搭建商品管理模块Servlet代码重构BaseServlet文件上传 MVC 是模型-视图-控制器(Model-View-Controller),它是一种设计模式,也…