python多线程与多进程开发实践及填坑记(2)

1. 前言

1.1. 概述

基于Flask、Pika、Multiprocessing、Thread搭建一个架构,完成多线程、多进程工作。具体需求如下:

  1. 并行计算任务:使用multiprocessing模块实现并行计算任务,提高计算效率、计算能力。
  2. 消息侦听任务:使用threading模块完成RabbitMQ消息队列的侦听任务,将接收到的数据放入multiprocessing.Queue中,以便并行计算任务处理。
  3. Web服务:使用Flask框架实现Web API服务,提供启停消息侦听任务、启停并行计算任务以及动态调整参数的功能。
  4. 任务交互:通过multiprocessing.Queue实现消息侦听任务与并行计算任务之间的资源交互。
  5. 非阻塞运行:使用threading模块非阻塞地运行Flask Web服务。

1.2. 续上一篇《python多线程与多进程开发实践及填坑记(1)》

python多线程与多进程开发实践及填坑记(1)

1.3. 重新启动侦听线程失败

程序没有报错,但是,没有启动侦听服务线程。

@app.route('/startlistening', methods=['GET'])
def start_listening():if stop_event.is_set():stop_event.clear()if not hasattr(app, 'pika_thread') or not app.pika_thread.is_alive():app.pika_thread = Thread(target=consume_from_rabbitmq_and_enqueue, args=(rabbitmq_params, rabbitmq_queue, data_queue))app.pika_thread.start()return jsonify({'status': 'listening'}), 200else:return jsonify({'status': 'already listening'}), 200

2. 原理解析

多线程下的Event(事件)原理与使用是并发编程中的重要概念,它主要用于线程间的同步与通信。下面我将从原理、类型、状态以及使用方法等方面详细介绍Event。

2.1. Event原理

Event(事件)是一个内核对象,用于线程间的同步与通信。它管理着一个全局的内部标志(Flag),这个标志通常有两种状态:已设置(True)和未设置(False)。线程可以通过Event对象来等待某个事件的发生,或者通知其他线程某个事件已经发生。

2.2. Event类型

Event主要分为两种类型:

  • 自动重置事件:当事件被触发(即Flag被设置为True)时,会唤醒一个正在等待的线程。随后,事件的Flag会自动重置为False,直到再次被触发。
  • 手动重置事件:当事件被触发时,会唤醒所有正在等待的线程。事件的Flag保持为True,直到程序显式地将其重置为False。

2.3. Event状态

Event对象的状态主要由其内部标志(Flag)决定,标志有两种可能的状态:

  • True(已设置):表示事件已发生,线程可以继续执行或不再被阻塞。
  • False(未设置):表示事件未发生,线程将处于阻塞状态,直到事件被触发。

2.4. Event使用方法

在多线程编程中,Event对象通常通过以下几个方法进行操作:

  1. 创建Event对象:
import threading  
event = threading.Event()
  1. 设置Event(触发事件):
    使用set()方法将Event对象的内部标志设置为True,唤醒所有等待的线程。
event.set()
  1. 清除Event(重置事件):
    使用clear()方法将Event对象的内部标志重置为False,使等待的线程再次进入阻塞状态(对于自动重置事件,这一步是自动的)。
event.clear()
  1. 等待Event(阻塞线程):
    使用wait(timeout=None)方法使当前线程阻塞,直到Event对象的内部标志为True或调用超时。
event.wait()  # 可以指定超时时间,如 event.wait(1) 表示等待1秒
  1. 检查Event状态:
    使用is_set()或isSet()(旧式Python中)方法检查Event对象的内部标志是否为True。
if event.is_set():  print("事件已发生")

2.5. 使用场景

Event在多线程编程中有广泛的应用场景,如:

  • 生产者-消费者模式:生产者线程在生成数据后触发Event,消费者线程等待Event来接收数据。
  • 线程间同步:当多个线程需要按照特定顺序执行时,可以使用Event来控制执行流程。
  • 条件等待:在某些条件下,线程需要等待某个事件的发生才能继续执行,这时可以使用Event来实现。

3. 重启线程解决方案

在多线程和多进程编程中,Event 对象是一个重要的同步原语。它允许一个线程向其他线程发送信号,以通知某些事件已经发生。具体到 stop_event 的使用,其主要作用是控制线程的启动和停止。

3.1. 修改代码

最初,是在start_listening中增加延时sleep代码,但是,没有起作用。

def start_listening():if stop_event.is_set():stop_event.clear()time.sleep(3)

有效的是在stop_listening中增加event.clear()代码。

@app.route('/startlistening', methods=['GET'])
def start_listening():if not stop_event.is_set():stop_event.clear()#time.sleep(2)# 此处,可以增加sleep延时启动监听if not stop_event.is_set():#stop_event.clear()        if not hasattr(app,'pika_thread') or not app.pika_thread.is_alive():app.pika_thread = Thread(target = consume_from_rabbitmq_and_enqueue, args = (rabbitmq_params, rabbitmq_queue,  data_queue))app.pika_thread.start()return jsonify({'status':'listening'}), 200else:return jsonify({'status':'already listening'}), 200else:stop_event.clear()return jsonify({'status':'error','message':'Stop event is set.'}), 400@app.route('/stoplistening', methods=['GET'])
def stop_listening():if hasattr(app,'pika_thread') and app.pika_thread.is_alive():stop_event.set()app.pika_thread.join()  # 等待线程结束del app.pika_thread     # 删除资源,确保重启成功time.sleep(2)  stop_event.clear()      # 新增起作用的代码!return jsonify({'status':'stopping'}), 200  else:return jsonify({'status':'not running'}), 400

3.2. 解释说明

  1. stop_event.clear() 在 start_listening 中的作用
    在 start_listening 中调用 stop_event.clear() 确保了事件的内部标志被设置为 False。这意味着:
  • 重新启动侦听线程时,如果事件的内部标志是 True,则不会启动新的线程。
  • 通过 clear() 将标志设置为 False,确保新的线程可以启动,并开始侦听 RabbitMQ 消息。
  1. stop_event.clear() 在 stop_listening 中的作用
  • 在 stop_listening 中调用 stop_event.clear() 确保了事件的内部标志被重置为 False,这样下一次调用 start_listening 时,不会被之前的停止状态影响。
  • clear() 的调用位置在 time.sleep(2) 之后,确保了有足够的时间让线程完全停止并释放资源。
  1. 为什么只增加 sleep 不足以解决问题
    仅仅增加 sleep 只是延迟了操作,并没有改变 stop_event 的状态。stop_event 仍然是设置状态(True),这会导致 start_listening 无法通过 if not stop_event.is_set() 的检查,从而不会启动新的线程。

3.3. 小结

在多线程控制中,使用 Event 对象来管理线程的启动和停止非常有效。set() 和 clear() 方法可以控制线程的执行和等待状态。正确地使用 stop_event.clear() 确保了你的应用程序在停止线程后可以重新启动新的线程,而不受之前的停止状态影响。这是你代码中的关键步骤,确保了线程控制逻辑的正确性。

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

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

相关文章

精准调整:数控切割机导轨的水平与垂直度校准!

滚柱导轨因其具有高承载、高精度、高稳定性和长寿命等特点,被广泛应用在重型设备、精密设备、自动化生产线、航空航天和半导体设备等领域。尤其是在数控切割机中的应用,最为广泛。 对于数控切割机来说,滚柱导轨的调整非常重要,是数…

文本编辑新境界!轻松一键,从表格中提取特定列并保存为TXT文本

在数字化办公的时代,表格数据的处理是每位职场人士必须面对的任务。然而,面对繁杂的表格数据和海量的信息,如何快速准确地提取我们所需的特定列内容,成为了许多人头疼的问题。今天,就让我来为大家分享一个高效编辑的新…

一对一服务,定制化小程序:NetFarmer助力企业精准触达用户

在当今这个日新月异的数字化时代,小程序以其独特的魅力和广泛的应用场景,正逐步成为企业出海战略中的璀璨明星。NetFarmer,作为业界领先的数字化出海服务商,不仅深谙HubSpot营销自动化的精髓,更在小程序领域展现了卓越…

mysql 字符集(character set)和排序规则(collation)

文章目录 概念1、字符集1.1、举例1.2、常见字符集 utf8 和 utf8mb4 区别1.3、字符集 使用 2、排序规则2.1、举例2.2、常见的排序规则 utf8mb4_bin 、utf8mb4_general_ci、utf8mb4_unicode_ci2.3、使用 概念 在 MySQL 中,字符集(character set&#xff0…

JAVA 对象存储OSS工具类(腾讯云)

对象存储OSS工具类 import com.qcloud.cos.COSClient; import com.qcloud.cos.ClientConfig; import com.qcloud.cos.auth.BasicCOSCredentials; import com.qcloud.cos.auth.COSCredentials; import com.qcloud.cos.model.ObjectMetadata; import com.qcloud.cos.model.PutObj…

SpringBoot的在线教育平台-计算机毕业设计源码68562

摘要 在数字化时代,随着信息技术的飞速发展,在线教育已成为教育领域的重要趋势。为了满足广大学习者对于灵活、高效学习方式的需求,基于Spring Boot的在线教育平台应运而生。Spring Boot以其快速开发、简便部署以及良好的可扩展性&#xff0c…

LeetCode 算法:二叉树的最近公共祖先 III c++

原题链接🔗:二叉树的最近公共祖先 难度:中等⭐️⭐️ 题目 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点…

扫地机器人如何利用图算法来进行避障策略和优化清扫路径的?

前言 扫地机器人是现代家庭中最常见的智能设备。其基本的核心组件由主控系统(大脑)、传感器等控制系统(感知系统)、动力供应系统(心脏)、清扫系统(四肢)组成。 扫地机器人的智能、高…

嵌入式UI开发-lvgl+wsl2+vscode系列:6、布局(Layouts)

一、前言 这节总结一下整体页面的布局方式,lvgl的布局方式比较少,目前只有flex和grid两大类布局,即弹性布局和网格布局,弹性布局一般就是指定相对位置,网格布局就是将整个页面划分为网格状,我们做其它的UI…

2-3 图像分类数据集

MNIST数据集是图像分类任务中广泛使用的数据集之一,但作为基准数据集过于简单,我们将使用类似但更复杂的Fashion-MNIST数据集。 %matplotlib inline import torch import torchvision # pytorch模型关于计算机视觉模型实现的一个库 from torch.utils i…

面试题 4:阐述以下方法 @classmethod, @staticmethod, @property?

欢迎莅临我的博客 💝💝💝,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

绘唐科技聚星文社是同款一键生成工具

聚星文社是同款一键生成工具 工具下载 绘唐科技成立于2015年,是一家专注于虚拟现实(VR)技术和产品开发的高科技企业。绘唐科技的目标是利用虚拟现实技术为人们带来更加沉浸式的体验,推动虚拟现实在各个领域的应用和发展。 绘唐科…

LabVIEW环境下OCR文字识别的实现策略与挑战解析

引言 在自动化测试领域,OCR(Optical Character Recognition,光学字符识别)技术扮演着重要角色,它能够将图像中的文字转换成机器可编辑的格式。对于使用LabVIEW约5个月,主要进行仪器控制与数据采集的你而言…

谈大语言模型动态思维流程编排

尽管大语言模型已经呈现出了强大的威力,但是如何让它完美地完成一个大的问题,仍然是一个巨大的挑战。 需要精心地给予大模型许多的提示(Prompt)。对于一个复杂的应用场景,编写一套完整的,准确无误的提示&am…

jmeter-beanshell学习1-vars使用获取变量和设置变量

最近又开始了用jmeter做自动化,不管怎么实现,都逃离不了用beanshell,最后把所有校验都放在了beanshell判断,效果还不错。 首先jmeter有很多beanshell相关的元件,取样器、前置处理器、后置处理器、断言,暂时…

南方航空阿里v2滑块验证码逆向分析思路学习

目录 一、声明! 二、介绍 三、请求流程分析: 1.拿验证码 2.提交第一次设备信息 3.提交第二次设备信息 4.提交验证 ​编辑 四、接口响应数据分析: 1.拿验证码 2.提交第一次设备信息 3.提交第二次设备信息 4.提…

代码随想录第43天|动态规划

121. 买卖股票的最佳时机 股票只能被买卖一次 dp[i][0] 持有股票所得到的最大现金, dp[i][1] 不持有股票所得的最大现金, 避免定义多个变量递推公式: dp[i][0] 可能是在之前买入, 也可能是在这次被买入 max(dp[i - 1][0],-prices[i])dp[i][1] 可能是在本次抛售, 也可能在之…

误删分区后的数据拯救:双管齐下恢复策略

在数字化时代,数据的价值日益凸显,而误删分区作为常见的数据安全威胁之一,常常让用户措手不及。本文将深入探讨误删分区的现象,并为您揭示两种高效的数据恢复方案,旨在帮助您在最短时间内找回失去的数据,同…

RH850系列芯片深度剖析 1.8-内存管理之MPU

RH850系列芯片深度剖析 1.8-内存管理之MPU 文章目录 RH850系列芯片深度剖析 1.8-内存管理之MPU一、MPU简介1.1 功能特性1.2 系统保护标识符(SPID)二、保护区域设置2.1 保护区域属性设置2.2 保护区域设置注意事项2.2.1 跨越保护区域边界2.2.2 无效的保护区域设置2.2.3 保护违规…

当火热的Mamba遇到火热的YOLO,会发生怎么样的反应吗?

作者:浙江师范大学 论文地址:https://arxiv.org/pdf/2406.05835 代码地址:https://github.com/HZAI-ZJNU/Mamba-YOLO 目录 前言一、摘要二、介绍二、相关工作2.1 实时目标检测器2.2 端到端的目标检测器2.3 视觉状态空间模型 三 方法3.1 基础知…