Python 多线程编程实战:threading 模块的最佳实践

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站AI学习网站。      

目录

前言

线程的创建

 1. 继承 threading.Thread 类

 2. 使用 threading.Thread 对象

线程的同步

 使用锁

线程的通信

 使用队列

线程池

 使用 concurrent.futures.ThreadPoolExecutor

最佳实践总结

 1. 使用适当数量的线程

 2. 使用线程安全的数据结构

 3. 使用上下文管理器简化线程的管理

总结


前言

Python 中的 threading 模块提供了一种简单而强大的多线程编程方式,可以在程序中同时执行多个任务,从而提高程序的效率和性能。本文将详细介绍如何使用 threading 模块进行多线程编程的最佳实践,包括线程的创建、同步、通信、线程池等内容,并提供丰富的示例代码帮助更好地理解和应用这些技术。

线程的创建

在 Python 中,可以通过继承 threading.Thread 类或使用 threading.Thread 对象的方式来创建线程。下面分别介绍这两种方式。

 1. 继承 threading.Thread 类

import threading
import timeclass MyThread(threading.Thread):def __init__(self, name):super().__init__()self.name = namedef run(self):print(f"Thread {self.name} is running")time.sleep(2)print(f"Thread {self.name} is finished")# 创建并启动线程
thread1 = MyThread("Thread 1")
thread2 = MyThread("Thread 2")thread1.start()
thread2.start()# 等待线程结束
thread1.join()
thread2.join()print("All threads are finished")

 2. 使用 threading.Thread 对象

import threading
import timedef thread_function(name):print(f"Thread {name} is running")time.sleep(2)print(f"Thread {name} is finished")# 创建并启动线程
thread1 = threading.Thread(target=thread_function, args=("Thread 1",))
thread2 = threading.Thread(target=thread_function, args=("Thread 2",))thread1.start()
thread2.start()# 等待线程结束
thread1.join()
thread2.join()print("All threads are finished")

线程的同步

在多线程编程中,线程的同步是一个重要的概念,可以确保多个线程按照特定的顺序执行,避免出现竞争条件和数据不一致等问题。常见的线程同步机制包括锁、信号量、事件等。

 使用锁

import threadingshared_resource = 0
lock = threading.Lock()def increment():global shared_resourcefor _ in range(100000):with lock:shared_resource += 1def decrement():global shared_resourcefor _ in range(100000):with lock:shared_resource -= 1thread1 = threading.Thread(target=increment)
thread2 = threading.Thread(target=decrement)thread1.start()
thread2.start()thread1.join()
thread2.join()print("Shared resource:", shared_resource)

线程的通信

在多线程编程中,线程之间的通信是一种重要的机制,可以实现数据的共享和交换。常见的线程通信方式包括队列、事件、条件变量等。

 使用队列

import threading
import queue
import timedef producer(q):for i in range(5):print("Producing", i)q.put(i)time.sleep(1)def consumer(q):while True:item = q.get()if item is None:breakprint("Consuming", item)time.sleep(2)q = queue.Queue()
thread1 = threading.Thread(target=producer, args=(q,))
thread2 = threading.Thread(target=consumer, args=(q,))thread1.start()
thread2.start()thread1.join()
q.put(None)
thread2.join()

线程池

线程池是一种常见的线程管理方式,可以提前创建一组线程,并且复用它们来执行任务,从而避免频繁创建和销毁线程的开销。

 使用 concurrent.futures.ThreadPoolExecutor

import concurrent.futures
import timedef task(name):print(f"Task {name} is running")time.sleep(2)return f"Task {name} is finished"with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:results = [executor.submit(task, i)for i in range(5)]for future in concurrent.futures.as_completed(results):print(future.result())

最佳实践总结

在使用 threading 模块进行多线程编程时,有一些最佳实践可以编写出高效可靠的多线程应用。

 1. 使用适当数量的线程

在设计多线程应用时,需要根据任务的性质和系统的资源情况来选择适当的线程数量。过多的线程可能导致资源竞争和上下文切换的开销,降低系统的性能,而过少的线程则可能无法充分利用系统的资源。因此,需要根据具体情况合理设置线程池的大小。

import concurrent.futures
import timedef task(name):print(f"Task {name} is running")time.sleep(2)return f"Task {name} is finished"# 使用ThreadPoolExecutor创建线程池,指定最大线程数为3
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:results = [executor.submit(task, i) for i in range(5)]for future in concurrent.futures.as_completed(results):print(future.result())

 2. 使用线程安全的数据结构

在多线程环境中,同时访问共享数据可能导致数据不一致的问题。因此,需要使用线程安全的数据结构来保证数据的一致性和可靠性。例如,可以使用 queue.Queue 来实现线程安全的队列。

import threading
import queue
import timedef producer(q):for i in range(5):print("Producing", i)q.put(i)time.sleep(1)def consumer(q):while True:item = q.get()if item is None:breakprint("Consuming", item)time.sleep(2)# 创建线程安全的队列
q = queue.Queue()# 创建生产者线程和消费者线程
thread1 = threading.Thread(target=producer, args=(q,))
thread2 = threading.Thread(target=consumer, args=(q,))# 启动线程
thread1.start()
thread2.start()# 等待线程结束
thread1.join()
q.put(None)
thread2.join()

 3. 使用上下文管理器简化线程的管理

在 Python 中,可以使用 with 语句和上下文管理器来简化线程的管理,确保线程在使用完毕后能够正确地关闭和释放资源,避免资源泄漏和异常情况。

import concurrent.futures
import timedef task(name):print(f"Task {name} is running")time.sleep(2)return f"Task {name} is finished"# 使用ThreadPoolExecutor创建线程池,指定最大线程数为3
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:results = [executor.submit(task, i) for i in range(5)]for future in concurrent.futures.as_completed(results):print(future.result())

总结

在 Python 多线程编程中,使用 threading 模块是一种强大的工具,能够提高程序的并发性和性能。本文详细介绍了线程的创建、同步、通信和线程池的最佳实践。通过合理设置线程数量、使用线程安全的数据结构以及简化线程管理,可以编写出高效可靠的多线程应用,充分利用多核处理器的优势,提升程序的性能和效率。通过本文的指导,可以更加深入地理解和应用 Python 中的多线程编程技术,从而开发出更加健壮和高效的应用程序。

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

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

相关文章

最新趋势揭秘:即时通讯开发中的人工智能应用

随着人工智能技术的快速发展和广泛应用,即时通讯开发领域迎来了一场前所未有的变革和机遇。在当今数字化时代,人工智能已经成为各行各业发展的重要引擎之一,即时通讯应用也不例外。人工智能技术的应用不仅可以提升即时通讯的用户体验和功能&a…

大数据基础设施搭建 - Flink

文章目录 一、上传并解压压缩包二、修改集群配置2.1 修改flink-conf.yaml文件2.2 修改workers文件2.3 修改masters文件2.4 分发配置文件2.5 修改其他两台机器的配置文件flink-conf.yaml 三、启动关闭集群(Standalone模式)四、访问WEB-UI五、向集群提交作…

常用日期和时间标准对比:HTML, ISO 8601, RFC 3339, RFC 5322

1. HTML, ISO 8601, RFC 3339, RFC 5322 对比 日期和时间,对于不同系统和平台之间的数据交换和互操作至关重要。本文将对比 HTML 标准、ISO 8601、RFC 3339 和 RFC 5322,为读者提供参考。 表格文字版见文末-附 1.1. 标准链接 HTML 标准: https://html…

【机器学习300问】27、高偏差与高方差是什么?他们对评估机器学习模型起何作用?

〇、回归模型举例 (1)第一种情况 你选择了一个简单的模型,比如一个直线,却想拟合类似抛物线分布的数据。 图1 (2)第二种情况 你选择了一个复杂的模型,比如一个四次多项式,想拟合类…

android高级面试题及答案,已拿offer

一、java相关 java基础 1、java 中和 equals 和 hashCode 的区别 2、int、char、long 各占多少字节数 3、int 与 integer 的区别 4、谈谈对 java 多态的理解 5、String、StringBuffer、StringBuilder 区别 6、什么是内部类?内部类的作用 7、抽象类和接口区别 java高…

2.模拟问题——6.活着的树

输入 500 3 100 200 150 300 470 471 输出 298 【提交地址】 简单思路 初始化一个全false的bool数组&#xff0c;表示树未被移走&#xff0c;然后根据输入值将数组内的对应序号值设为true表示已经移走。 最后统计false的数目即为剩下的树数。 #include <cstdio> #incl…

步进电机驱动器接法

实物 参数 共阳极&#xff1a; 使能给高电平有效 共阴极&#xff1a; 使能给低电平有效 整体接线 参考内容 B站UP范辉

20240305-2-海量数据处理常用技术概述

海量数据处理常用技术概述 如今互联网产生的数据量已经达到PB级别&#xff0c;如何在数据量不断增大的情况下&#xff0c;依然保证快速的检索或者更新数据&#xff0c;是我们面临的问题。 所谓海量数据处理&#xff0c;是指基于海量数据的存储、处理和操作等。因为数据量太大无…

字节跳动热门的前端开源项目

字节跳动开源官网 Arco Dsign Arco Design 是一套设计系统&#xff0c;主要服务于字节跳动旗下中后台产品的体验设计和技术实现。它的目标在于帮助设计师与开发者解放双手、提升工作效率&#xff0c;并高质量地打造符合业务规范的中后台应用。它拥有系统的设计规范和资源&…

(学习日记)2024.03.05:UCOSIII第七节:SysTick+任务时间片

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

计算机网络 网络原理之Http

目录 1 前言2 什么是http的一次交互&#xff1f;3 理解“协议”二字4 认识URL4.1 简介4.2 URL的编码和解码(urlencode和urldecode) 5 抓包工具 fiddler6 http和https的区别7 http 头8 HTTP 状态码9 常见的 Http 服务器 1 前言 为什么要了解Http原理呢&#xff1f;因为http原理…

gitlab的安装

1、下载rpm 安装包 (1)直接命令下载 wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-11.6.10-ce.0.el7.x86_64.rpm&#xff08;2&#xff09;直接去服务器上下载包 Index of /gitlab-ce/yum/el7/ | 清华大学开源软件镜像站 | Tsinghua Open Source…