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

news2024/9/21 20:46:42

更多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下载

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

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

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

相关文章

基于Java SSM框架实现KTV点歌系统项目【项目源码+论文说明】

基于java的SSM框架实现KTV点歌系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个KTV点歌系统,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述KTV点歌系…

【模电】放大电路的性能指标

放大电路的性能指标 放大倍数输入电阻输出电阻通频带非线性失真系数最大不失真输出电压最大输出功率与效率 下图所示为放大电路的示意图。 对于信号而言,任何一个放大电路均可看成一个两端口网络。左边为输入端口,当内阻为 R s R\tiny s Rs的正弦波信号…

C语言练习记录(蓝桥杯练习)(小蓝数点)

目录 小蓝数点 第一题程序的输出结果是?: 第二题下面代码的执行结果是什么?: 第三题下面代码的执行结果是什么?: 第四题关于关系操作符说法错误的是?: 第五题对于下面代码段,y的值为? 第六题sum 21 …

Microsoft Expression Web - 网页布局

在本章中,我们将介绍网页的基本布局。在创建我们的网页布局之前,我们需要考虑我们的内容,然后设计我们希望如何呈现该内容,因为它是在我们的网站上可见的内容。 由我们如何呈现我们的内容,以便我们的观众找到我们的网…

人工智能概论

一、关键技术 人工智能包含了七项关键技术: 1. 机器学习: 机器学习是研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能,是人工智能技术的核心。 从学习模式划分,分…

Redis:主从复制

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

DCDC前馈电容与RC串并联电路

一、RC串并联电路特性分析 1、RC串联电路 RC 串联的转折频率: f01/(2πR1C1),当输入信号频率大于 f0 时,整个 RC 串联电路总的阻抗基本不变了,其大小等于 R1。 2、RC并联电路 RC 并联电路的转折频率&…

【Linux基础开发工具】yum生态vim的配置与使用

目录 前言 1. Linux 软件包管理器 yum 1.1 什么是yum 1.2 快速上手yum 1.3 yum生态 2. Linux编辑器vim 2.1 vim的模式 2.2 vim使用技巧 3. vim编辑器辅助功能配置 3.1 配置 3.2 用户sudo权限配置 总结 前言 Linux基础指令与权限之后,Linux系统开发工具的使用…

[操作系统] 文件管理

文章目录 5.1 磁盘调度算法1. 先来先服务算法( First Come First Served, FCFS) 算法2. 最短寻道时间优先算法( Shortest Seek Time First, SSTF) 算法3. 扫描算法( SCAN ) 算法4. 循环扫描算法( Circular Scan, CSCAN ) 算法5. LOOK 与 CLOOK 算法 5.2 进程写文件时&#xff0…

2023.11.27 使用anoconda搭建tensorflow环境

2023.11.27 使用anoconda搭建tensorflow环境 提供一个简便安装tensorflow的方法 1. 首先安装anoconda,安装过程略,注意安装的时候勾选安装anoconda prompt 2. 进入anoconda prompt 3. 建立python版本 conda create -n tensorflow1 python3.84. 激活t…

BUUCTF [ACTF新生赛2020]swp 1

BUUCTF:https://buuoj.cn/challenges 题目描述: 得到的 flag 请包上 flag{} 提交。 密文: 下载附件,得到一个.tar文件。 解题思路: 1、使用WinRAR解压.tar文件,得到两个.zip文件。 解压wget.zip文件,得…

如何有效的进行 E2E

一、前言 本文作者介绍了什么是E2E测试以及E2E测试测什么,并从对于被测系统、测试用例、测试自动化工具、测试者四个方面的要求,介绍了如何保证E2E测试有效性,干货满满,值得学习。 二、什么是E2E测试 相信每一个对自动化测试感…

MySQL图书管理系统(49-94)源码

-- 九、 子查询 -- 无关子查询 -- 比较子查询&#xff1a;能确切知道子查询返回的是单值时&#xff0c;可以用>&#xff0c;<&#xff0c;&#xff0c;>&#xff0c;<&#xff0c;!或<>等比较运算符。 -- 49、 查询与“俞心怡”在同一个部门的读者的借…

Python VIP 付费漫画,无需充值随便霍霍,零基础也能学会!

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 环境使用: Python 3.10 Pycharm 模块使用: requests >>> pip install requests 数据请求模块 parsel >>> pip install parsel 数据解析模块 …

【开源】基于Vue+SpringBoot的独居老人物资配送系统

项目编号&#xff1a; S 045 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S045&#xff0c;文末获取源码。} 项目编号&#xff1a;S045&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询社区4…

Embedding压缩之hash embedding

在之前的两篇文章 CTR特征重要性建模&#xff1a;FiBiNet&FiBiNet模型、CTR特征建模&#xff1a;ContextNet & MaskNet中&#xff0c;阐述了特征建模的重要性&#xff0c;并且介绍了一些微博在特征建模方面的研究实践&#xff0c;再次以下面这张图引出今天的主题&#…

销售客户分配管理细则

随着市场竞争的不断加剧&#xff0c;销售团队的有效管理变得愈发重要。其中&#xff0c;客户分配是销售团队成功的关键之一。一个科学合理的销售客户分配管理细则不仅可以提高销售团队的整体工作效率&#xff0c;还能够优化客户体验&#xff0c;促使销售业绩持续增长。下面是一…

Jmeter接口测试:jmeter_逻辑控制器_随机控制器随机顺序控制器

随机控制器 当该控制器下有多个子项时&#xff0c;每次循环会随机执行其中一个 Ignore sub-controller block&#xff08;忽略子控制器模块&#xff09; 如果勾选了此项&#xff0c;随机控制器下的子控制器中的多个子项只会被执行一个 随机顺序控制器 当该控制器下有多个子项…

5. 文件属性和目录

5. 文件属性和目录 1. Linux 系统的文件类型1.1 普通文件1.2 目录文件1.3 字符设备文件和块设备文件1.4 符号链接文件1.5 管道文件1.6 套接字文件 2. stat 系统调用2.1 struct stat 结构体2.2 st_mode 变量2.3 struct timespec 结构体 3. fstat 和 lstat 函数3.1 fstat 函数3.2…

反欺诈指南:东南亚数字经济反欺诈注意事项

目录 东南亚各类网络欺诈肆虐 科技助力东南亚反欺诈 东南亚做反欺诈需要注意四个方面 据谷歌、淡马锡和贝恩公司发布的一份报告显示&#xff0c;尽管东南亚地区的经济增长有所放缓&#xff0c;但2023年数字经济仍预计创造约100亿美元的收入&#xff0c;数字支付占该地区总交易额…