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 time

class MyThread(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

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

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

shared_resource = 0
lock = threading.Lock()

def increment():
    global shared_resource
    for _ in range(100000):
        with lock:
            shared_resource += 1

def decrement():
    global shared_resource
    for _ in range(100000):
        with lock:
            shared_resource -= 1

thread1 = 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 time

def 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:
            break
        print("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 time

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

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

def 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:
            break
        print("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 time

def 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 中的多线程编程技术,从而开发出更加健壮和高效的应用程序。

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

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

相关文章

如何开发分销商城小程序呢_打造分销利器

打造分销利器,揭秘如何开发一款成功的分销商城小程序 在移动互联网时代,小程序以其轻便、快捷的特点,成为了连接用户与服务的桥梁。其中,分销商城小程序更是受到了广大商家的青睐。那么,如何开发一款成功的分销商城小…

PCM会重塑汽车OTA格局吗(1)

目录 1.汽车OTA概述 2.ST如何考虑OTA? 2.1 Stellar四大亮点 2.2 PCM技术视角下的OTA 3.小结 1.汽车OTA概述 随着智能网联汽车的飞速发展,汽车OTA也越来越盛行; 目前来讲OTA分为FOTA和SOTA(Software-over-the-air)两种,区别…

解决win10串口一直被占用

目录 问题描述解决方法 问题描述 串口设备一直被占用,换串口也没有用,永远都是串口正在被使用,甚至换硬件设备也不行,都快烦死了 解决方法 输入这个: 删除这个玩意,计算机\HKEY_LOCAL_MACHINE\SYSTEM\Cu…

Reqable爬虫抓包工具(国产网络调试工具)

官网界面截图: 官网地址:https://reqable.com/zh-CN/windows/ 历史由来: Reqable的前身是HttpCanary(一款Android平台应用程序),但是国内开发者推翻了所有的技术栈,并用C和Flutter重写&#x…

Tensorflow2.0笔记 - 计算梯度

本笔记主要记录tf.GradientTape和tf.gradient的用法 import tensorflow as tf import numpy as nptf.__version__#要计算梯度的所有参数计算过程必须放到gradient tape中 #with tf.GradientTape as tape: w tf.constant(1.) x tf.constant(2.)with tf.GradientTape() as tap…

在线部署ubuntu20.04服务器,安装jdk、mysql、redis、nginx、minio

查看服务器版本为20.04 lsb_release -a服务器初始账号密码 sxd / 123456 首先,更改自身密码都输入123456 sudo passwd 创建最高权限root账号,密码为 123456 su root 更新源列表 sudo apt-get update 安装 openssh-server和vim,途中输入y sudo ap…

46、Numpy手推共空间模式CSP,用于脑电EEG信号分类

一、Numpy实现CSP公式及对应的代码 CSP全部流程: 1、CSP先将数据按照类别分类,两类数据可分为E1、E2 2、计算分类后的原始数据的协方差矩阵: 方差矩阵: C协方差矩阵,E原始EEG信号,trace求迹 实现代码&a…

使用java的Stream流进行Collectors.groupingBy分组后生成Map,对Map进行删除原集合是否会发生改变

在Java中,当我们使用Collectors.groupingBy方法对集合进行分组操作时,生成的新映射(Map)是基于原始集合(allItems)的数据结构和内容创建的。这意味着,如果你更改了新的映射allItemMap中的值&…

xss.haozi.me:0X12

</script> <script>alert(1)\</script>

[数据结构]OJ一道------用栈实现队列

题目来源:232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 解题思路来源:力扣官方题解 https://leetcode.cn/problems/implement-queue-using-stacks/solutions/632369/yong-zhan-shi-xian-dui-lie-by-leetcode-s-xnb6/ 首先我们先来看题目: 给的代码: typedef s…

基于springboot的计算机类考研交流平台(源码+论文)

目录 前言 一、功能设计 二、功能实现 三、库表设计 四、论文 前言 教育发展不仅仅是关乎到每一位学生的大事情&#xff0c;更是一个国家发展的基本方针。教育发展当中最重要的就是高校学生的教学工作&#xff0c;信息技术也是能够改变我们生活方式的一种强大力量&#xf…

EdgeX Foundry - Modbus 设备服务

文章目录 一、Modbus 设备服务1.概述2.协议属性3.数据类型转换3.1.读命令3.2.写命令3.3.何时转换数据3.4.支持的转换 二、连接 Modbus 设备1.docker-comepse2.设备配置文件3.Modbus 配置4.启动 EdgeX Foundry5.Modbus 测试工具6.访问 UI6.1. consul6.2. EdgeX Console 7.测试7.…

【深度学习笔记】计算机视觉——单发多框检测(SSD)

单发多框检测&#xff08;SSD&#xff09; sec_ssd 在 sec_bbox— sec_object-detection-dataset中&#xff0c;我们分别介绍了边界框、锚框、多尺度目标检测和用于目标检测的数据集。 现在我们已经准备好使用这样的背景知识来设计一个目标检测模型&#xff1a;单发多框检测&…

CSS小知识

文章目录 1. box-sizing属性描述的是什么&#xff0c;可以设置为哪些值&#xff1f; 1. box-sizing属性描述的是什么&#xff0c;可以设置为哪些值&#xff1f; box-sizing 属性定义如何计算一个元素的总宽度和总高度&#xff0c;主要设置是否需要加上内边距(padding)和边框等…

http代理IP适合什么场景使用?HTTP代理IP的优势在哪里呢?

HTTP代理IP在多种场景下都能发挥重要作用&#xff0c;尤其是在网络请求处理、数据抓取、爬虫应用以及隐私保护等方面。下面&#xff0c;我们将详细探讨HTTP代理IP适用的场景以及其所具备的优势。 一、HTTP代理IP适合什么场景使用&#xff1f; 1. 网络请求处理&#xff1a;在进行…

第六篇:人工智能与机器学习技术VS数据迁移(Data Migration)--- 我为什么要翻译介绍美国人工智能科技巨头IAB公司?

(source: 图片来自麻省理工官网&#xff09; IAB平台&#xff0c;使命和功能 IAB成立于1996年&#xff0c;总部位于纽约市。 作为美国的人工智能科技巨头社会媒体和营销专业平台公司&#xff0c;互动广告局&#xff08;IAB- the Interactive Advertising Bureau&#xff09;…

opencv dnn模块 示例(24) 目标检测 object_detection 之 yolov8-pose 和 yolov8-obb

前面博文【opencv dnn模块 示例(23) 目标检测 object_detection 之 yolov8】 已经已经详细介绍了yolov8网络和测试。本文继续说明使用yolov8 进行 人体姿态估计 pose 和 旋转目标检测 OBB 。 文章目录 1、Yolov8-pose 简单使用2、Yolov8-OBB2.1、python 命令行测试2.2、opencv…

java算法第十天 | ● 栈和队列理论基础 ● 232.用栈实现队列 ● 225. 用队列实现栈

栈和队列理论基础 栈 &#xff1a;先进后出队列 &#xff1a;先进先出 Java中队列Queue的操作 队列 使用Queue接口创建队列 &#xff0c;Queue的实现类有LinkedList和ArrayDeque。最常用的实现类是LinkedList。 Queue的六种方法&#xff1a; add&#xff08;&#xff09;和…

基于SpringBoot+MYSQL的网页时装购物系统

目录 1、 前言介绍 2、主要技术 3、系统流程分析 3.1、系统登录流程图 3.2、添加信息流程图 3.3、删除信息流程图 4、系统体系结构 4.1、时装购物系统的结构图 4.2、登录系统结构图 4.3、时装购物系统结构图 5、数据库设计原则 5.1、管理员信息属性图 5.2、用户管…

CSS文本样式值,web前端开发资料

正文 什么是行内元素&#xff1f; display属性为inline的元素为行内元素&#xff0c;英文&#xff1a;inline element&#xff0c;其中文叫法有多种&#xff0c;如&#xff1a;内联元素、内嵌元素、行内元素、直进式元素等。 特点&#xff1a; 和其他元素都在一行上&#x…