Python多线程使用详解

news2024/11/22 19:23:41

46a7411747fc445fbccb142c6e34fef4.png


 概要

 

多线程是一种并发编程的技术,通过同时执行多个线程来提高程序的性能和效率。在Python中,我们可以使用内置的threading模块来实现多线程编程。

 

一、创建线程

在使用多线程之前,我们首先需要了解如何创建线程。Python提供了threading模块,我们可以通过继承Thread类或使用函数来创建线程。

1.1 示例代码

下面是一个示例代码,展示了如何创建线程:

import threading

# 继承Thread类创建线程
class MyThread(threading.Thread):
    def run(self):
        # 线程执行的代码
        print("Hello, World!")

        # 使用函数创建线程
def my_function():
    # 线程执行的代码
    print("Hello, World!")

    # 创建线程对象并启动线程
thread1 = MyThread()
thread2 = threading.Thread(target=my_function)
thread1.start()
thread2.start()

在这个示例中,我们使用继承Thread类和使用函数的两种方式创建了线程。对于继承Thread类的方式,我们需要重写run()方法,将线程要执行的代码放在该方法中。对于使用函数的方式,我们需要将线程要执行的函数作为target参数传递给Thread对象。最后,通过调用start()方法来启动线程。需要注意的是,多线程的执行顺序是不确定的,线程的启动顺序不一定等于线程的执行顺序。

 

二、线程同步

在多线程编程中,线程之间可能会共享资源,因此需要进行线程同步来保证资源的正确访问。Python提供了多种线程同步机制,例如互斥锁、信号量和事件等。

2.1 互斥锁

互斥锁是一种最基本的线程同步机制,它可以确保同一时刻只有一个线程可以访问共享资源。Python中的threading模块提供了Lock类来实现互斥锁。

2.2 示例代码

下面是一个示例代码,展示了如何使用互斥锁进行线程同步:

import threading

# 共享资源
count = 0

# 创建互斥锁
lock = threading.Lock()

def increment():
    global count
    # 获取锁
    lock.acquire()
    try:
        # 修改共享资源
        count += 1
    finally:
        # 释放锁
        lock.release()

        # 创建多个线程并启动
threads = []
for _ in range(10):
    thread = threading.Thread(target=increment)
    threads.append(thread)
    thread.start()

    # 等待所有线程结束
for thread in threads:
    thread.join()

    # 打印结果
print("Count:", count)

在这个示例中,我们使用互斥锁来保证对共享资源count的访问是线程安全的。在线程的increment()函数中,我们首先使用lock.acquire()方法获取锁,然后在try-finally语句块中修改共享资源,并最后使用lock.release()方法释放锁。需要注意的是,在使用互斥锁时,一定要确保在获取锁后,无论发生何种情况,都能够释放锁,以避免产生死锁的情况。

2.3 线程间通信

多个线程之间可能需要进行数据的传递和共享,Python提供了多种线程间通信的机制,例如使用queue模块实现的队列。

2.4 示例代码

下面是一个示例代码,展示了如何使用队列进行线程间通信:

import threading
import queue

# 创建队列对象
q = queue.Queue()

def producer():
    for i in range(5):
        # 生产数据
        q.put(i)
        print("Produced:", i)

def consumer():
    while True:
        # 获取数据
        data = q.get()
        if data is None:
            break
        print("Consumed:", data)

        # 创建生产者线程和消费者线程
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)

# 启动线程
producer_thread.start()
consumer_thread.start()

# 等待生产者线程结束
producer_thread.join()

# 添加终止标志到队列
q.put(None)

# 等待消费者线程结束
consumer_thread.join()

在这个示例中,我们使用队列来实现生产者-消费者模型的线程间通信。生产者线程通过q.put()方法向队列中添加数据,消费者线程通过q.get()方法从队列中获取数据。为了退出消费者线程,我们在队列中添加了一个特殊的终止标志None。

 

三、线程池

线程池是一种管理和复用线程的机制,它可以避免频繁地创建和销毁线程,提高线程的利用效率。Python中的concurrent.futures模块提供了ThreadPoolExecutor类来实现线程池。

3.1 示例代码

下面是一个示例代码,展示了如何使用线程池:

import concurrent.futures

# 定义任务函数
def my_task(name):
    print("Task", name, "is running.")

    # 创建线程池
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # 提交任务
    for i in range(5):
        executor.submit(my_task, i)

在这个示例中,我们使用ThreadPoolExecutor类创建了一个最大线程数为5的线程池。通过调用executor.submit()方法,我们可以提交任务给线程池执行。需要注意的是,在使用线程池时,我们不需要显式地创建线程,线程的创建和管理都由线程池来完成。线程池会自动根据任务的数量和系统资源情况来管理线程的执行。

 

四、结论

通过本文的介绍,我们了解了Python中多线程的使用方法,包括线程的创建、线程同步、线程间通信以及线程池等内容。多线程编程可以提高程序的性能和效率,但同时也需要注意线程同步和资源共享的问题。合理地设计和使用多线程,可以使我们的程序更加高效和可靠。

 

欢迎点赞收藏转发,感谢🙏

 

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

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

相关文章

你信不信,只要学几天javascript就可以使用纯原生实现五星评分效果 【附完整代码】

🚀 个人主页 极客小俊 ✍🏻 作者简介:web开发者、设计师、技术分享博主 🐋 希望大家多多支持一下, 我们一起进步!😄 🏅 如果文章对你有帮助的话,欢迎评论 💬点赞&#x1…

动态规划DP(七) 股票交易

1.股票交易 在股票买卖的最佳时机问题中,给定一个数组,数组中的每个元素代表某一天的股票价格。你可以进行多次买入和卖出,但是必须在再次购买前卖出之前的股票。目标是找到最大的利润。 动态规划可以用于解决股票交易类的问题,…

ssl证书和域名过期提醒平台

由于经常忘记了证书是否要过期,导致过期了出现一些访问上的问题 docker安装部署 当然可以接入mysql,默认使用的sqlite version: "3" services:domain-admin:image: mouday/domain-admin:latestcontainer_name: domain-adminvolumes:- ./data:/…

菜鸡shader:L8 UV扰动动画——火焰和简单水面

文章目录 卡通火焰代码最后效果 水面代码最后效果 这此做笔记的两个shader其实是课程的作业,课程主要也是讲UV扰动的概念,因为课程的shader在另一台电脑上,做笔记就暂时不带他们了,简单做下火焰和水面的shader。 卡通火焰 火焰这…

FreeRTOS(队列)

队列 什么是队列? 队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任 务间传递信息。 为什么不使用全局变量? 如果使用全局变量,兔子(任务1)修改了变量 a …

新版studio没法筛选Log

目录 方式一 简单粗暴,针对怀旧者,可切回原版log视图 方式二 学习新的log过滤方法 升级新版本AndroidStudio后,log日志变成以下样子,发现之前过滤error,infor的tab都不见了,瞬间不淡定了,查阅资料才发现…

DAY45:动态规划(五)背包问题:01背包理论基础+二维DP解决01背包问题

文章目录 背包问题大纲01背包01背包暴力解法01背包二维DP解法二维DP数组的解法DP数组含义递推公式初始化二维DP数组(比较重要)遍历顺序(比较重要) 二维DP数组完整版思路总结返回值为什么是二维数组最后一个元素DP推导过程与数组含…

selenium 根据期刊信息获取知网文献信息 pt.1

哈喽大家好,我是咸鱼 之前写过一篇获取知网文献信息的文章,看了下后台数据还挺不错 所以咸鱼决定再写一篇知网文献信息爬取的文章 需要注意的是文章只是针对某一特定期刊的爬取,希望小伙伴们把关注点放在如何分析网页以及如何定位元素上面…

python实现前后端学生管理系统(前后端不分离)

⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章 ⭐作者主页:逐梦苍穹 ⭐所属专栏:项目。 目录 1、前言2、简述实现内容首页注册登录管理员 3、详细代码3.1、项目目录3.2、templates3.2.1、testxz…

赛效:如何在线转换图片格式

1:点击左侧菜单栏里的“格式转换”,然后在转换格式菜单栏里点击上传按钮。 2:选择下方输出格式,点击右下角“开始转换”。 3:稍等片刻转换成功后,点击图片右下角的“下载”,将转换后的图片保存到…

UE5《Electric Dreams》项目PCG技术解析 之 PCGCustomNodes详解(四)ApplyHierarchy

继续解析《Electric Dreams》项目中的自定义节点和子图:ApplyHierarchy 文章目录 前导文章标准组合拳ApplyHierarchyExecute with ContextIteration Loop BodyPoint Loop Body应用场景 小结 前导文章 《UE5《Electric Dreams》项目PCG技术解析 之 理解Assembly&…

【Android】APT与JavaPoet学习与实战

PS:本文讲解的APT全称为Annotation Processing Tool,而非是Android Performance Tuner,这两种工具简称皆为APT,前者是“注释处理工具”,后者是“Android性能调试器”。 本文分别使用Java、kotlin 语言进行开发&#xf…

做一个游戏小项目有多简单?

认识一个朋友,学了很多年的 python, 还停留在 helloworld 阶段,每次拿起又放下,是不是很熟悉?每天都在想,我要学编程,我要学编程,但是又不知道从何学起,学了一点又不知道怎么用&…

java并发编程原理-----线程

目录 上下文切换 java代码创建线程的两种方式 线程的五个状态 线程join方法 多线程之间的影响 上下文切换 CPU的每一个核心同一时刻只能执行一个线程,但是我们会发现电脑同一时刻现实会进行几千个线程,这就是cpu在快速的切换执行线程,由…

Python中的迭代器

一、介绍 在Python中,迭代器是一种访问集合元素的方式,可以用于遍历数据集中的元素,而不需要事先知道集合的大小。迭代器可以被用于循环语句中,例如for循环,来遍历集合中的每个元素。 Python中的迭代器是一个实现了迭…

将Windows系统上的音频、视频通过iTunes传输到iPhone上

这个地方需要下载安装版的iTunes 下载地址: https://www.apple.com/itunes/download/win64 不要从Windows的APP Store中下载iTunes,不好使。 安装完成后,如果是导入一个文件夹中的资料,则点击 【文件】》【将文件夹添加到资料库】…

岛屿数量 (力扣) dfs + bfs (JAVA)

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的…

在内卷化竞争时代,金龙鱼重返增长的关键到底是什么?

提到欧丽薇兰、胡姬花、香满园、海皇、金味、丰苑、锐龙洁劲100、丸庄酱油等品牌,多数消费者的第一反应是什么?多数消费者认为是某个不知名的新品牌。问题的重点不在产品,而在主品牌定位。 事实上,这都是金龙鱼母公司益海嘉里旗下的品牌。内行都知道益海…

“坏邻居”导致的kafka生产者TPS下降原因排查

背景: 今天测试了两种不同的场景下kafka producer的tps性能数据,两种场景下都是使用3个线程,每个线程都是对应一个kafka producer,测试发送到kafka集群的消息的量,两个场景的区别是场景A只发送kafka消息,场…

自定义类型

目录 什么是自定义类型 结构体 结构体的声明 常规结构体的声明形式 特殊的结构体声明形式 匿名结构体: 匿名结构体的重命名: 注意事项: 结构体的自引用 什么是结构体的自引用 结构体变量的定义与初始化 方法一: 方法…