python创建线程和结束线程

👽发现宝藏

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

python创建线程和结束线程

在 Python 中,线程是一种轻量级的执行单元,允许我们在程序中同时执行多个任务。线程的创建和结束是多线程编程中的核心概念之一。在本文中,我们将学习如何使用 Python 创建线程,并探讨如何优雅地结束线程。

创建线程

Python 中创建线程非常简单,可以使用 threading 模块来实现。下面是一个简单的例子:

import threading
import timedef print_numbers():for i in range(1, 6):print(i)time.sleep(1)# 创建线程
thread = threading.Thread(target=print_numbers)# 启动线程
thread.start()# 主线程等待子线程执行完成
thread.join()print("线程执行完成!")

在这个例子中,我们创建了一个名为 print_numbers 的函数,该函数用于打印 1 到 5 的数字。然后,我们使用 threading.Thread 类创建了一个新的线程,并指定了要执行的目标函数。最后,通过调用 start() 方法启动线程,通过 join() 方法等待线程执行完成。

结束线程

结束线程通常是为了让程序在不需要线程继续执行时能够正常退出,或者在特定条件下终止线程的执行。在 Python 中,线程是无法直接终止的,但是可以通过设置标志位或者发送信号的方式让线程自行退出。下面是一个简单的例子:

import threading
import time# 全局标志位,控制线程执行
is_running = Truedef count_numbers():i = 1while is_running:print(i)i += 1time.sleep(1)# 创建线程
thread = threading.Thread(target=count_numbers)# 启动线程
thread.start()# 主线程等待一段时间后修改标志位,结束线程
time.sleep(5)
is_running = Falseprint("等待线程执行完成...")
thread.join()print("线程执行完成!")

在这个例子中,我们创建了一个名为 count_numbers 的函数,该函数会不断地打印数字,并通过一个全局变量 is_running 控制线程的执行。在主线程中,我们等待了 5 秒后将 is_running 设置为 False,从而让线程自行退出。

安全结束线程

除了设置标志位的方式外,有时候我们可能需要更加安全和可靠地结束线程。Python 中的线程并没有提供直接的方法来强制终止线程,但可以使用一些技巧来安全地结束线程,比如使用 Thread 对象的 Event

下面是一个使用 Event 来结束线程的示例:

import threading
import time# 创建 Event 对象
stop_event = threading.Event()def count_numbers():i = 1while not stop_event.is_set():print(i)i += 1time.sleep(1)# 创建线程
thread = threading.Thread(target=count_numbers)# 启动线程
thread.start()# 主线程等待一段时间后设置 Event,结束线程
time.sleep(5)
stop_event.set()print("等待线程执行完成...")
thread.join()print("线程执行完成!")

在这个例子中,我们创建了一个 Event 对象 stop_event,线程在每次循环中检查该事件是否被设置。在主线程中,我们等待了 5 秒后设置了 stop_event,从而结束了线程的执行。

异常处理

在线程中,异常的处理也是一个重要的问题。如果线程中发生了异常而没有处理,整个线程可能会意外终止。因此,在线程中要使用 try-except 语句来捕获异常,并进行适当的处理。

下面是一个简单的例子:

import threading
import timedef task():try:# 这里是线程执行的任务print("任务开始...")time.sleep(3)raise Exception("人为抛出异常")except Exception as e:print(f"捕获到异常:{e}")# 创建线程
thread = threading.Thread(target=task)# 启动线程
thread.start()# 主线程等待线程执行完成
thread.join()print("线程执行完成!")

在这个例子中,线程中的任务抛出了一个异常,但由于我们在 task 函数中使用了 try-except 语句,因此异常被捕获并打印出来,而线程并没有意外终止。

使用线程池管理线程

在实际开发中,如果需要频繁地创建和销毁线程,可能会导致性能下降。为了更有效地管理线程,可以使用线程池来重用线程对象。Python 提供了 concurrent.futures 模块,其中的 ThreadPoolExecutor 类可以帮助我们轻松地管理线程池。

下面是一个使用线程池的例子:

from concurrent.futures import ThreadPoolExecutor
import timedef task(n):print(f"任务 {n} 开始...")time.sleep(2)print(f"任务 {n} 完成!")# 创建线程池
with ThreadPoolExecutor(max_workers=3) as executor:# 提交任务给线程池执行for i in range(1, 6):executor.submit(task, i)print("所有任务执行完成!")

在这个例子中,我们使用 ThreadPoolExecutor 创建了一个最大工作线程数为 3 的线程池。然后,我们提交了 5 个任务给线程池执行。线程池会自动管理线程的创建和销毁,以及任务的调度。

使用 threading.Thread 的子类

除了直接使用 threading.Thread 类外,我们还可以通过继承 threading.Thread 创建自定义的线程类。这样做可以更好地组织代码,并且可以在子类中重写 run() 方法来定义线程执行的逻辑。

下面是一个简单的例子:

import threading
import timeclass MyThread(threading.Thread):def __init__(self, name):super().__init__()self.name = namedef run(self):print(f"{self.name} 线程开始执行...")time.sleep(3)print(f"{self.name} 线程执行完成!")# 创建线程实例并启动
thread1 = MyThread("Thread 1")
thread2 = MyThread("Thread 2")thread1.start()
thread2.start()# 等待线程执行完成
thread1.join()
thread2.join()print("所有线程执行完成!")

在这个例子中,我们定义了一个 MyThread 类,继承自 threading.Thread,并重写了 run() 方法来定义线程执行的逻辑。然后,我们创建了两个 MyThread 的实例,并启动了这两个线程。

线程同步与共享资源

在多线程编程中,经常会遇到多个线程同时访问共享资源的情况。为了避免竞争条件和数据不一致的问题,需要使用线程同步机制来保护共享资源。

使用锁(Lock)

锁是最常见的线程同步机制之一,Python 中的 threading.Lock 类可以用来创建锁对象。在访问共享资源之前,线程可以通过调用 acquire() 方法获取锁,访问完成后再调用 release() 方法释放锁。

下面是一个使用锁来保护共享资源的例子:

import threadingshared_resource = 0
lock = threading.Lock()def update_shared_resource():global shared_resourcefor _ in range(100000):lock.acquire()shared_resource += 1lock.release()# 创建多个线程来更新共享资源
threads = []
for _ in range(5):t = threading.Thread(target=update_shared_resource)threads.append(t)t.start()# 等待所有线程执行完成
for t in threads:t.join()print("共享资源的值为:", shared_resource)

在这个例子中,我们创建了一个名为 shared_resource 的共享变量,然后使用 threading.Lock 创建了一个锁对象 lock。在 update_shared_resource 函数中,我们使用锁来保护对 shared_resource 的访问,从而避免了多个线程同时修改共享资源的问题。

使用条件变量(Condition)

条件变量是另一种常见的线程同步机制,Python 中的 threading.Condition 类可以用来创建条件变量对象。条件变量通常与锁结合使用,可以在满足特定条件时通知等待的线程。

下面是一个使用条件变量来实现生产者-消费者模式的例子:

import threading
import timeMAX_ITEMS = 5
items = []
condition = threading.Condition()def producer():for i in range(10):time.sleep(1)with condition:if len(items) >= MAX_ITEMS:print("仓库已满,生产者等待...")condition.wait()print("生产者生产一个商品")items.append(i)condition.notify()def consumer():for i in range(10):time.sleep(1.5)with condition:while not items:print("仓库为空,消费者等待...")condition.wait()item = items.pop(0)print(f"消费者消费了商品 {item}")condition.notify()# 创建生产者和消费者线程并启动
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)producer_thread.start()
consumer_thread.start()# 等待线程执行完成
producer_thread.join()
consumer_thread.join()print("所有商品已被生产和消费完毕!")

在这个例子中,我们使用了条件变量 condition 来实现生产者-消费者模式。生产者线程在仓库满时等待,消费者线程在仓库空时等待,并在生产或消费完成后通过 notify() 方法通知等待的线程。

使用队列实现线程间通信

除了使用锁和条件变量等同步机制外,还可以使用队列来实现线程间的安全通信。Python 中的 queue.Queue 类提供了线程安全的队列实现,可以在多个线程之间安全地传递数据。

下面是一个使用队列实现生产者-消费者模式的例子:

import threading
import queue
import timeMAX_ITEMS = 5
queue = queue.Queue(MAX_ITEMS)def producer():for i in range(10):time.sleep(1)try:queue.put(i, block=True, timeout=1)print("生产者生产一个商品")except queue.Full:print("仓库已满,生产者等待...")def consumer():for i in range(10):time.sleep(1.5)try:item = queue.get(block=True, timeout=1)print(f"消费者消费了商品 {item}")except queue.Empty:print("仓库为空,消费者等待...")# 创建生产者和消费者线程并启动
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)producer_thread.start()
consumer_thread.start()# 等待线程执行完成
producer_thread.join()
consumer_thread.join()print("所有商品已被生产和消费完毕!")

在这个例子中,我们使用了 queue.Queue 类来实现生产者-消费者模式。生产者线程通过 put() 方法向队列中添加商品,消费者线程通过 get() 方法从队列中取出商品。当队列已满时,生产者线程会等待;当队列为空时,消费者线程会等待。

使用队列实现线程间通信的好处在于,它提供了一种简单而安全的方式来传递数据,避免了显式的锁和条件变量的使用。

定时结束线程

有时候,我们希望线程在一定时间内执行完毕或者超时退出。Python 中可以利用定时器来实现这一功能。定时器可以在指定的时间后触发一个事件,我们可以利用这个特性来控制线程的执行时间。

下面是一个使用定时器结束线程的例子:

import threading
import timedef task():print("线程开始执行...")time.sleep(3)  # 模拟线程执行时间print("线程执行完成!")# 创建线程
thread = threading.Thread(target=task)# 启动线程
thread.start()# 定时器,3秒后设置线程结束标志
def set_thread_finished():print("定时器触发,设置线程结束标志...")thread.finished = Truetimer = threading.Timer(3, set_thread_finished)
timer.start()# 主线程等待线程执行完成
thread.join()print("线程执行完成!")

在这个例子中,我们创建了一个定时器 timer,在 3 秒后触发 set_thread_finished 函数,该函数设置了线程的结束标志。线程在执行时会检查结束标志,如果标志被设置,则提前退出。这样就实现了在指定时间后结束线程的功能。

使用 threading.Event 实现线程等待

除了定时器,我们还可以使用 threading.Event 来实现线程的等待和超时退出。Event 是线程间通信的一种机制,可以用来设置信号、等待信号等操作。

下面是一个使用 Event 实现线程等待的例子:

import threading
import time# 创建 Event 对象
event = threading.Event()def task():print("线程开始执行...")event.wait(3)  # 等待事件触发,超时时间为3秒if event.is_set():print("事件被触发,线程执行完成!")else:print("超时退出,线程执行未完成!")# 创建线程
thread = threading.Thread(target=task)# 启动线程
thread.start()# 等待一段时间后设置事件
time.sleep(2)
print("等待2秒后设置事件...")
event.set()# 主线程等待线程执行完成
thread.join()print("线程执行完成!")

在这个例子中,线程在执行时等待事件的触发,如果在3秒内事件被设置,则线程执行完成;否则,线程会在超时后退出。这样就实现了在指定时间内结束线程的功能。

总结

在本文中,我们探讨了在 Python 中创建线程、结束线程以及线程管理的多种方法。我们从创建线程的基础开始,介绍了使用 threading 模块创建线程的方法,并展示了如何优雅地结束线程。接着,我们深入讨论了线程同步与共享资源的问题,介绍了使用锁、条件变量和队列等机制来保护共享资源、实现线程间通信的方法。然后,我们探讨了如何使用定时器和事件来实现线程的定时结束和超时退出,从而更灵活地控制线程的执行时间。

总的来说,本文全面介绍了多线程编程中的关键概念和技术,并提供了丰富的代码示例来帮助读者更好地理解和应用这些技术。通过合理地使用线程管理和同步机制,我们可以编写出高效、可靠的多线程程序,更好地利用计算资源,提高程序的性能和可维护性。希望本文对读者在 Python 多线程编程方面有所帮助。

在这里插入图片描述

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

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

相关文章

进程概念(进程第1篇)【Linux复习篇】

目录 1、冯诺依曼体系结构怎么画?中央处理器是什么?存储器是什么?每个部分有什么作用? 2、什么是操作系统? 3、什么叫进程?操作系统如何管理进程的? 4、怎么查看进程? 5、C语言…

基于MLP算法实现交通流量预测(Pytorch版)

在海量的城市数据中,交通流量数据无疑是揭示城市运行脉络、洞察出行规律的关键要素之一。实时且精准的交通流量预测不仅能为交通规划者提供科学决策依据,助力提升道路使用效率、缓解交通拥堵,还能为公众出行提供参考,实现个性化导…

指令和界面【Linux】

指令和界面 前言一、指令 vs 界面交互的需求满足需求的第一阶段——指令满足需求的第二阶段-界面时间 二、指令和界面交互区别为什么要学命令行总结 前言 Linux操作系统提供了丰富的命令行界面和图形用户界面工具,用户可以根据自己的需求选择适合的界面进行操作。命…

【好书推荐7】《机器学习平台架构实战》

【好书推荐7】《机器学习平台架构实战》 写在最前面《机器学习平台架构实战》编辑推荐内容简介作者简介目  录前  言本书读者内容介绍充分利用本书下载示例代码文件下载彩色图像本书约定 🌈你好呀!我是 是Yu欸 🌌 2024每日百字篆刻时光&…

论文阅读:BEVBert: Multimodal Map Pre-training for Language-guided Navigation

BEVBert:语言引导导航的多模态地图预训练 摘要 现存的问题:目前大多数现有的预训练方法都采用离散的全景图来学习视觉-文本关联。这要求模型隐式关联全景图中不完整、重复的观察结果,这可能会损害智能体的空间理解。 本文解决方案&#xf…

TikTok账号0播放是限流了吗?想要播放破万,试试这些方法!

前言 账号0播放问题,想必困扰着许多的TikTok运营同学。精心制作的短视频发布在TikTok,不是零播放,就是仅自己可见。那么,TikTok账号0播放是不是真的意味着被限流了呢?本篇总结了账号0播放的原因并附上解决方案&#xf…

[Flutter3] Json转dart模型举例

记录一下 Android studio plugin -> FlutterJsonBeanFactory 处理json转dart 模型 案例 json字符串, 一个 response的data返回数据 {"code":1,"msg":"\u64cd\u4f5c\u6210\u529f","data":{"list":{"id":"8…

SwiftUI 5.0(iOS 17.0)触摸反馈“震荡波”与触发器模式趣谈

概览 要想创作出一款精彩绝伦的 App,绚丽的界面和灵动的动画并不是唯一吸引用户的要素。有时我们还希望让用户真切的感受到操作引发的触觉反馈,直击使用者的灵魂。 所幸的是新版 SwiftUI 原生提供了实现触觉震动反馈的机制。在介绍它之后我们还将进一步…

等保测评之主机测评详解(二级)

等保测评之主机测评详解(二级)服务器——Windows 身份鉴别: 测评项a): a)应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换; 整改方…

antd中Upload上传图片宽高限制以及上传文件的格式限制

项目中有一个需求,要上传轮播图,且有尺寸要求,所以就需要在上传图片的时候进行尺寸限制,使用了Upload组件,需要在组件的beforeUpload方法中进行限制。 定义一个上传前的方法,并且添加一个图片尺寸获取的方…

【Redis】Zset 数据类型

文章目录 常用命令zaddzcard & zcountzrange & zrevrangezpopmax & bzpopmaxzpopmin & bzpopminzrank & zrevrankzscore & zremzremrangebyrank & zremrangebyscorezincrby 多个集合间的交互命令交集 & zinterstore并集 & sunionstore 内部…

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡 配置ssh远程连接docker1.端口映射2.配置ssh 在docker中使用nvidia显卡配置CUDA 注意:之前已经创建过容器的,需要打包成镜像,重新创建容器,因为要在创建…

【C++庖丁解牛】C++11---右值引用和移动语义

🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 1 左值引用和右值引用2 左…

第一个Spring Boot程序

目录 一、Spring Boot介绍 二、创建Spring Boot项目 1、插件安装(专业版不需要) 2、创建SpringBoot项目 (1)这里如果插件下载失败,解决方案: (2)项目启动失败,解决…

web测试基础知识

目录 web系统的基础 web概念(worldwideweb) 网络结构 发展 架构 B/S C/S P2P 工作原理 静态页面 动态页面 web客户端技术 浏览器的核心--渲染引擎 web服务器端技术 web服务器 应用服务器 集群环境 数据库 案例-URL 协议类型 主机名 端口 IP地址 分类 …

C#开发的全套成熟的LIS系统源码JavaScript+SQLserver 2012区域云LIS系统源码

C#开发的全套成熟的LIS系统源码JavaScriptSQLserver 2012区域云LIS系统源码 医院云LIS系统是一套成熟的实验室信息管理系统,目前已在多家三级级医院应用,并不断更新。云LIS系统是为病人为中心、以业务处理为基础、以提高检验科室管理水平和工作效率为目标…

贪心算法练习day.1

理论基础 贪心算法是一种常见的解决优化问题的方法,其基本思想就是在问题的每个决策阶段,都选择当前看起来最优的选择,即贪心地做出局部的最优决策,以此得到全局的最优解,例如在十张面额不同的钞票,让我们…

润申信息企业标准化管理系统 AddNewsHandler.ashx 任意用户创建漏洞复现

0x01 产品简介 润申信息科技企业标准化管理系统通过给客户提供各种灵活的标准法规信息化管理解决方案,帮助他们实现了高效的标准法规管理,完成个性化标准法规库的信息化建设。 0x02 漏洞概述 润申信息企业标准化管理系统 AddNewsHandler.ashx 接口处存在任意用户创建漏洞,…

Linux安装部署Tomcat

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ Linux安装部署Tomcat //将tomcat压缩包解压到对…

python识别电脑是windows还是linux

代码实现 import osif os.name nt:print(当前操作系统是 Windows) elif os.name posix:print(当前操作系统是 Linux 或 Unix 类型的系统) else:print(未知的操作系统)