Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
Python高效队列实现:仅保留特定类型最新元素的策略_创想鸟

Python高效队列实现:仅保留特定类型最新元素的策略

Python高效队列实现:仅保留特定类型最新元素的策略

本教程探讨在python生产者-消费者模式中,如何设计一个特殊队列,使其能同时处理重要任务(a类)和非重要任务(b类)。核心挑战在于当新的b类任务到达时,需要高效地移除队列中所有旧的b类任务,同时保持a类任务和整体fifo顺序。文章将介绍如何利用双向链表实现这一机制,提供o(1)时间复杂度的特定元素移除,并附带详细代码示例和使用说明,确保队列在复杂条件下的高效运行。

需求分析与传统队列的局限性

在许多并发编程场景中,生产者-消费者模式是常见的架构。我们经常需要一个缓冲队列来协调生产者和消费者之间的速度差异。然而,当队列中的元素类型不同,且对特定类型的元素有特殊的淘汰规则时,传统队列(如Python的collections.deque或queue.Queue)可能难以高效满足需求。

具体来说,我们的目标是实现一个满足以下条件的队列:

线程安全:在多线程环境下能够正确工作。FIFO (先进先出):整体上遵循先进先出原则。重要任务(A类):所有A类任务都应保留在队列中,表示重要且必须执行的任务。非重要任务(B类)的特殊处理:当一个新的B类任务到达时,队列中所有先前的B类任务都应被移除,仅保留最新的B类任务。这表示B类任务是可替代的,我们只关心其最新状态。顺序保持:元素在队列中的相对顺序应被保留。消费者正常消费:消费者按照正常的FIFO规则从队列头部取出元素。

使用Python内置的list或collections.deque来实现这种带有条件淘汰的队列,会面临效率问题。例如,要移除队列中间的特定元素,通常需要遍历队列来查找并删除,这会导致O(N)的时间复杂度,对于长队列而言性能开销巨大。

基于双向链表的O(1)高效移除策略

为了解决传统队列在特定元素移除上的效率问题,我们可以采用双向链表(Doubly Linked List)作为底层数据结构。双向链表的优势在于,如果能够直接获取到某个节点的引用,那么移除该节点的操作可以在O(1)时间复杂度内完成,因为它只需要修改前后节点的指针。

立即学习“Python免费学习笔记(深入)”;

在Python中,llist模块提供了一个高效的双向链表实现,llist.dllist。我们将利用这个特性来构建我们的特殊队列。核心思想是:维护一个对队列中当前“最新非重要任务”节点的引用。当新的非重要任务到来时,如果旧的非重要任务存在,我们可以直接通过引用将其从链表中移除,然后将新任务添加到链表末尾并更新引用。

队列实现

首先,定义任务的基本结构。我们将使用dataclasses来创建简单的任务类。

Elser AI Comics Elser AI Comics

一个免费且强大的AI漫画生成工具,助力你三步创作自己的一出好戏

Elser AI Comics 522 查看详情 Elser AI Comics

from llist import dllistfrom dataclasses import dataclassimport threading# 定义基础任务类@dataclassclass Task:    name: str# 定义非重要任务类,继承自基础任务类class UnimportantTask(Task):    passclass SpecialQueue:    def __init__(self):        self.queue = dllist()  # 使用dllist作为底层队列        self.unimportant_task_node = None  # 存储最新非重要任务的节点引用        self.lock = threading.Lock() # 用于多线程环境的锁    def add(self, task):        """        向队列中添加任务。        如果是非重要任务,会移除队列中现有的旧非重要任务。        """        with self.lock: # 确保线程安全            # 将新任务添加到链表末尾            new_node = self.queue.appendright(task)            if isinstance(task, UnimportantTask):                # 如果是新的非重要任务                if self.unimportant_task_node:                    # 如果队列中已经存在一个非重要任务,则移除它                    self.queue.remove(self.unimportant_task_node)                # 更新引用,指向最新的非重要任务节点                self.unimportant_task_node = new_node    def next(self):        """        从队列头部取出下一个任务。        """        with self.lock: # 确保线程安全            if not self.queue:                return None # 队列为空            # 从链表头部取出任务            task = self.queue.popleft()            # 如果取出的任务是非重要任务,且其节点引用与我们存储的最新非重要任务节点一致            # 说明这个非重要任务已经被消费,清空引用            if isinstance(task, UnimportantTask) and self.unimportant_task_node is not None and self.unimportant_task_node.value == task:                self.unimportant_task_node = None            return task    def is_empty(self):        """        检查队列是否为空。        """        with self.lock:            return not bool(self.queue)

代码解析:

Task 和 UnimportantTask 类:通过继承关系区分两种任务类型。SpecialQueue 类:__init__:self.queue = dllist():初始化一个llist.dllist实例作为实际的存储结构。self.unimportant_task_node = None:这是一个关键变量,用于存储队列中当前唯一保留的非重要任务的dllist节点引用。self.lock = threading.Lock():引入线程锁,确保在多线程环境下对队列的add和next操作是原子性的,防止数据竞争。add(self, task):首先,使用 self.lock 保护操作,确保线程安全。new_node = self.queue.appendright(task):将新任务添加到链表末尾。dllist的appendright方法会返回新创建的节点对象。if isinstance(task, UnimportantTask):检查新任务是否为非重要任务。if self.unimportant_task_node::如果self.unimportant_task_node不为None,说明队列中已经有一个非重要任务。self.queue.remove(self.unimportant_task_node):通过存储的节点引用,以O(1)时间复杂度将其从链表中移除。self.unimportant_task_node = new_node:更新self.unimportant_task_node,使其指向新添加的非重要任务的节点。next(self):同样,使用 self.lock 保护操作。task = self.queue.popleft():从链表头部取出任务。if isinstance(task, UnimportantTask) and self.unimportant_task_node is not None and self.unimportant_task_node.value == task::这里需要注意,如果弹出的任务是非重要任务,并且它就是我们之前记录的那个最新非重要任务,那么在它被消费后,我们就需要将 self.unimportant_task_node 清空,表示队列中不再有待处理的非重要任务。is_empty(): 辅助方法,检查队列是否为空。

使用示例

以下代码演示了如何使用SpecialQueue以及其行为:

# 创建队列实例tasks = SpecialQueue()# 添加重要任务tasks.add(Task('A1'))tasks.add(Task('A2'))# 添加第一个非重要任务 (B1)tasks.add(UnimportantTask('B1'))# 添加另一个重要任务tasks.add(Task('A3'))# 添加第二个非重要任务 (B2)。此时B1会被移除。tasks.add(UnimportantTask('B2'))# 添加第三个非重要任务 (B3)。此时B2会被移除。tasks.add(UnimportantTask('B3'))# 添加最后一个重要任务tasks.add(Task('A4'))print("--- 消费队列中的任务 ---")# 消费队列中的任务while not tasks.is_empty():    task = tasks.next()    print(task)

预期输出:

--- 消费队列中的任务 ---Task(name='A1')Task(name='A2')Task(name='A3')UnimportantTask(name='B3')Task(name='A4')

输出分析:

从输出中可以看出:

A1、A2、A3、A4 这些重要任务都按照它们被添加的顺序保留并被消费。B1 和 B2 这两个非重要任务在 B3 被添加时被成功淘汰,最终只有 B3 保留在队列中,并作为唯一的非重要任务被消费。整体的FIFO顺序得到了维护,重要任务和最终的非重要任务都按照它们在队列中的相对位置被取出。

注意事项与总结

线程安全:虽然llist.dllist本身不是为多线程并发访问设计的,但通过在SpecialQueue的add和next方法中引入threading.Lock,我们确保了对共享资源的互斥访问,从而实现了线程安全。在实际的生产者-消费者应用中,这是必不可少的一步。llist模块的安装:使用前需要通过pip install llist安装该模块。内存管理:dllist在移除节点时会正确断开链接,Python的垃圾回收机制会处理不再引用的节点对象。适用场景:这种设计模式特别适用于需要高效地替换队列中特定类型“状态”的场景,例如,一个传感器队列只关心最新的读数,或者一个用户操作队列只关心最新的“取消”指令。

通过巧妙地结合双向链表的数据结构特性和对特定节点引用的管理,我们成功地实现了一个高效且灵活的定制化队列。这种方法在保证FIFO顺序的同时,解决了传统队列在处理特定条件下的元素淘汰问题,提供了一个时间复杂度为O(1)的解决方案。

以上就是Python高效队列实现:仅保留特定类型最新元素的策略的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/905512.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
学习如何在苹果iPhone 14的主屏幕上展示个性签名
上一篇 2025年11月28日 22:50:45
为动态修改类结构的Python装饰器提供类型提示:Mypy插件实战指南
下一篇 2025年11月28日 22:51:07

相关推荐

  • 美团外卖节日优惠券领取入口_美团节日活动优惠券获取方法

    节日期间可通过美团外卖首页“膨胀红包”、搜索品牌关键词、参与“神抢手”秒杀、邀请好友助力及关注官方社交媒体口令等五种方法领取优惠券,具体包括完成任务积累红包、领取0元饮品券、抢购低价商品券、获取大额免单券和兑换口令红包。 如果您在节日期间准备通过美团外卖订餐,但未能找到可用的优惠券入口,则可能是由于…

    2026年9月21日
    100
  • MAC系统磁盘空间不足怎么办_Mac磁盘空间清理与管理技巧

    Mac存储空间不足时,应先使用系统自带的存储管理工具分析并优化存储,通过“关于本机”进入“管理”界面,启用优化选项;接着手动删除不常用应用及其在Application Support和Caches中的残留文件;再进入资源库清理Caches和Logs中的缓存与日志;随后在“避免杂乱”中查找并删除大型无…

    2026年9月21日
    000
  • MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南

    MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南

    mysql原生全文搜索功能存在明显局限,需结合外部搜索引擎才能满足复杂需求。1. mysql全文搜索适用于小数据量、简单查询场景,但分词能力弱,尤其对中文支持差,查询功能有限,无法实现模糊查询、纠错等高级功能,且性能随数据量增长显著下降。2. 外部搜索引擎如elasticsearch(es)和sph…

    2026年9月21日 • 用户投稿
    000
  • Android应用中实现游戏循环与UI更新的正确姿势

    本文旨在解决Android应用开发中,开发者尝试使用传统游戏循环(如while(running))导致应用无响应或崩溃的问题。核心内容是阐明Android事件驱动的UI模型,指导开发者如何正确初始化UI组件、设置事件监听器,并通过事件回调机制实现逻辑更新和UI刷新,避免阻塞主线程,确保应用的流畅运行…

    2026年9月21日
    700
  • bilibili客户端如何开启省流量模式_bilibili客户端省流量功能的设置指南

    首先调整默认视频清晰度至“流畅”或“480P”,再开启省流播放模式以优化数据传输,最后关闭自动缓存与预加载功能,从而有效降低B站移动数据消耗。 如果您在使用移动数据网络观看B站视频时发现流量消耗过快,可能是未开启针对性的省流量设置。通过调整客户端内的相关选项,可以有效降低数据使用量。以下是具体的操作…

    2026年9月21日
    000
  • MAC的随航(Sidecar)功能怎么使用_MAC Sidecar功能使用教程

    首先确认设备兼容性,确保Mac和iPad满足硬件与系统要求,并登录同一Apple ID。接着开启Wi-Fi和蓝牙,使两设备处于同一网络。通过控制中心“显示器”选项选择iPad名称,无线连接即可建立;或使用数据线进行有线连接以获得更稳定体验。连接后可在“系统设置-显示器-随航”中配置扩展或镜像模式,启…

    2026年9月21日
    000
  • MacBookPro怎么下VSCode_MacBookPro下载安装VSCode详细教程

    访问code.visualstudio.com下载Mac通用版安装包;2. 解压后将Visual Studio Code.app拖入“应用程序”文件夹;3. 首次运行需右键选择“打开”以绕过安全限制;4. 推荐安装Python、Prettier等常用插件并配置环境变量;5. 若字体模糊可调整zoom…

    2026年9月21日
    000
  • HuggingFace的AI混合工具如何使用?开发AI模型的实用操作教程

    HuggingFace的AI混合工具核心在于其生态系统设计,通过Transformers库的统一接口、Pipelines的抽象封装、Datasets与Accelerate等工具,实现多模型组合与微调。它允许开发者将复杂任务拆解,利用预训练模型如BERT、T5等,通过Python逻辑串联不同Pipel…

    2026年9月21日
    1000
  • Java中高效查找时空事件重叠的方法

    本文探讨了在Java中高效查找具有空间和时间范围定义的事件之间重叠的解决方案。核心思想是将时空事件编码为二维矩形,然后利用专业的空间索引结构(如R树、四叉树或PH树)进行快速查询。通过这种方法,可以显著提升在大规模数据集中识别事件重叠的效率,并提供了使用Tinspin索引库的示例代码和实践建议。 时…

    2026年9月21日
    000
  • 苹果手机怎么卸载app

    一、常规删除方式 最常用的卸载方法非常直观。只需长按想要移除的app图标,图标会进入抖动状态,同时左上角出现一个“×”标志。点击这个“×”,随后在跳出的提示框中选择“删除app”,即可完成卸载。卸载后,该应用将从主屏幕消失,并释放其所占用的存储空间。 二、保留数据的卸载方式 若你只是暂时不使用某个应…

    2026年9月21日
    000
  • PHPComposer怎么安装_PHPComposer依赖管理工具安装与使用指南

    PHPComposer是PHP的依赖管理工具,类似npm或pip。需先安装PHP,再下载并验证composer-setup.php,执行安装生成composer.phar,推荐全局安装至/usr/local/bin/composer,运行composer –version验证。使用com…

    2026年9月21日
    000
  • 如何为iPhone12ProMax下载固件?快速获取方法分享

    首先通过苹果官方开发者中心、第三方固件网站或iTunes/Finder获取iPhone 12 Pro Max的正确固件文件,确保来源可靠并校验完整性,再进行系统降级或修复操作。 如果您尝试为您的iPhone 12 Pro Max进行系统降级或修复系统错误,但无法找到合适的固件文件,则可能是由于下载渠…

    2026年9月21日
    000
  • 一周学会蝴蝶号无人直播的完整课程计划推荐

    一周学会蝴蝶号无人直播的完整课程计划推荐一周学会蝴蝶号无人直播的完整课程计划推荐一周学会蝴蝶号无人直播的完整课程计划推荐一周学会蝴蝶号无人直播的完整课程计划推荐

    掌握“蝴蝶号”无人直播的核心要义,一周内可搭建初步系统并具备独立操作能力。1.第一天厘清概念并完成基础环境搭建;2.第二天熟悉obs基础操作与场景构建;3.第三天准备高质量内容素材并确定风格;4.第四天设置自动化逻辑与推流配置;5.第五天处理互动机制及常见问题;6.第六天进行首次正式直播并复盘;7.…

    2026年9月21日 • 用户投稿
    100
  • 使用EventBus实现Android实时速度显示与后台保存教程

    本教程详细介绍了如何在Android应用中实现实时速度的显示与后台保存功能。通过利用前台服务(Foreground Service)获取位置数据,并结合EventBus库实现服务与UI界面(MainActivity)之间的实时数据通信,确保即使应用处于后台或屏幕关闭时,速度数据也能持续更新并显示在用…

    2026年9月21日
    000
  • google浏览器CPU占用率过高怎么解决_google浏览器CPU占用过高解决方法

    Chrome CPU占用过高可通过清除缓存、禁用高耗能扩展、结束高占用进程、更新浏览器、关闭硬件加速及禁用Software Reporter Tool解决。 如果您在使用Google Chrome浏览器时发现电脑运行缓慢或风扇狂转,很可能是由于Chrome的CPU占用率过高导致系统资源被大量消耗。以…

    2026年9月21日
    000
  • VSCode报错怎么显示中文_VSCode错误信息本地化与中文显示教程

    安装中文语言包可将VSCode界面和错误提示转为中文,提升使用便捷性;但外部工具如编译器、解释器生成的报错仍为英文,因VSCode仅显示其原始输出,无法翻译。 在VSCode中让报错信息显示中文,核心在于安装并启用官方的中文(简体)语言包。这不仅仅是针对错误信息,而是将整个VSCode的用户界面本地…

    2026年9月21日
    000
  • Java ConcurrentSkipListMap在并发场景下应用

    ConcurrentSkipListMap是基于跳跃表实现的线程安全有序映射,支持高并发读写与高效范围查询,适用于需排序的并发场景,如排行榜系统;相比ConcurrentHashMap,它提供有序性与导航操作,但插入查找为O(log n),内存开销较大,适合读多写少或需区间扫描的业务。 在高并发场景…

    2026年9月21日
    100
  • Steam游戏平台下载缓存怎么清理_Steam清理下载缓存的方法

    清理Steam下载缓存可解决下载慢、中断或安装失败问题。首先可通过客户端设置中的“清除下载缓存”功能操作,随后重新登录账户;若无效,可手动删除Steam安装目录下的appcache和depotcache文件夹;此外,重置网络配置并执行netsh winsock reset与ipconfig /flu…

    2026年9月21日
    000
  • VSCode怎么设置变量窗口_VSCode调试时变量监视面板使用教程

    答案:配置launch.json并设置断点后,通过VSCode调试界面的变量和监视面板可实时查看变量值。具体包括正确设置program路径,利用变量面板查看作用域内变量,使用监视面板添加表达式或变量进行持续跟踪,结合调试按钮控制执行流程,并可通过条件断点、控制台输出、debugger语句、Sourc…

    2026年9月21日
    100
  • MySQL 大型历史数据表结构设计与优化指南

    本文旨在为处理大量客户历史交易数据的MySQL数据库设计提供专业指导。我们将探讨如何构建高效、可扩展的表结构,重点关注主键设计、数据分区、实时数据摄入以及性能优化策略,以确保系统能够稳定支持百万级乃至亿级数据量的查询需求。 MySQL大型历史数据表结构设计与优化 在处理大量历史数据,特别是涉及到多用…

    2026年9月21日
    000

发表回复

登录后才能评论
关注微信