当前位置: 首页 > news >正文

状态机——并行分支聚合

并行分支聚合

    • 1、问题描述
    • 2、方案一:利用 EnumSet 收集前置状态(最推荐,纯轻量级)
      • 2.1、定义状态和事件
      • 2.2、状态机上下文
      • 2.3、测试运行
    • 3、方案二:利用“二进制位(Bitmask)”进行状态压缩

1、问题描述

当你的状态机不再是简单的“单线流转”(A -> B -> C),而是涉及多条件聚合(比如 A、B、C 三个前置条件都完成后,才能触发转换为 D)时,这在状态机中被称为 Fork/Join(并行分支聚合) 场景。

在 Java 枚举中实现这种“多合一”的逻辑,最核心的变化是:状态机不能再只依赖一个“当前状态”变量,而是需要引入“状态位(Flags)”或者“事件收集池”来记录前置条件的完成情况。

2、方案一:利用 EnumSet 收集前置状态(最推荐,纯轻量级)

我们可以把 A、B、C 看作是 D 的三个前置子任务。当 A、B、C 各自完成后,检查集合是否集齐,集齐了就自动合成为 D。

2.1、定义状态和事件

importjava.util.EnumSet;publicenumCompositeState{INIT,// 初始状态A_DONE,// A部分完成B_DONE,// B部分完成C_DONE,// C部分完成D;// 最终合成态 D}// 触发的事件(比如三个部门分别审批、或三个组件分别就绪)enumEvent{FINISH_A,FINISH_B,FINISH_C}

2.2、状态机上下文

在 Context 中,我们用 EnumSet 来实时记录已经完成了哪些部分。

publicclassSynthesisContext{privatefinalStringid;privateCompositeStatecurrentStatus=CompositeState.INIT;// 用来存放已经就绪的前置状态集合privatefinalEnumSet<CompositeState>readyParts=EnumSet.noneOf(CompositeState.class);publicSynthesisContext(Stringid){this.id=id;}// 统一的事件触发入口publicsynchronizedvoidhandleEvent(Eventevent){if(currentStatus==CompositeState.D){System.out.println("已经处于最终态 D,忽略事件: "+event);return;}// 根据事件,把对应的状态加入“已就绪”池switch(event){caseFINISH_A:readyParts.add(CompositeState.A_DONE);break;caseFINISH_B:readyParts.add(CompositeState.B_DONE);break;caseFINISH_C:readyParts.add(CompositeState.C_DONE);break;default:}System.out.println("事件 "+event+" 触发,当前已就绪组件: "+readyParts);// 检查是否满足合成 D 的条件if(readyParts.contains(CompositeState.A_DONE)&&readyParts.contains(CompositeState.B_DONE)&&readyParts.contains(CompositeState.C_DONE)){this.currentStatus=CompositeState.D;System.out.println("🎉 【🎉大功告成】A+B+C 满足条件,成功合成为状态: "+currentStatus);}}publicCompositeStategetCurrentStatus(){returncurrentStatus;}}

2.3、测试运行

publicclassMain{publicstaticvoidmain(String[]args){SynthesisContextcontext=newSynthesisContext("Task_001");// 异步或乱序触发事件context.handleEvent(Event.FINISH_B);// 触发 Bcontext.handleEvent(Event.FINISH_A);// 触发 ASystem.out.println("当前整体状态: "+context.getCurrentStatus());// 依然不是 DSystem.out.println("-------------------------------------");context.handleEvent(Event.FINISH_C);// 触发 C,此时 A+B+C 齐全System.out.println("当前整体状态: "+context.getCurrentStatus());// 变成 D}}
事件 FINISH_B 触发,当前已就绪组件: [B_DONE] 事件 FINISH_A 触发,当前已就绪组件: [A_DONE, B_DONE] 当前整体状态: INIT ------------------------------------- 事件 FINISH_C 触发,当前已就绪组件: [A_DONE, B_DONE, C_DONE] 🎉 【🎉大功告成】A+B+C 满足条件,成功合成为状态: D 当前整体状态: D

3、方案二:利用“二进制位(Bitmask)”进行状态压缩

如果 A、B、C 是极其严格的布尔条件(要么完,要么没完),并且你希望把这个状态极其轻量地存在数据库的一个数字字段里,可以用位运算。

  • A 完成 = 0b001 (十进制 1)
  • B 完成 = 0b010 (十进制 2)
  • C 完成 = 0b100 (十进制 4)
  • D (全部完成) = 0b111 (十进制 7)
publicenumBitOrderState{// 定义每个事件对应的二进制位FINISH_A(1<<0),// 1FINISH_B(1<<1),// 2FINISH_C(1<<2);// 4privatefinalintmask;BitOrderState(intmask){this.mask=mask;}publicintgetMask(){returnmask;}// 核心逻辑:当前状态码通过“位或”运算叠加,满 7 则代表合成 DpublicstaticintnextState(intcurrentProgress,BitOrderStateevent){// 叠加状态intnewProgress=currentProgress|event.getMask();if(newProgress==7){System.out.println("位状态满 0b111(7),成功合成为 D!");}else{System.out.println("当前进度二进制码: "+Integer.toBinaryString(newProgress));}returnnewProgress;}}

使用方式:

intprogress=0;// 初始状态 0progress=BitOrderState.nextState(progress,BitOrderState.FINISH_A);// 变为 1progress=BitOrderState.nextState(progress,BitOrderState.FINISH_C);// 变为 5 (1|4)progress=BitOrderState.nextState(progress,BitOrderState.FINISH_B);// 变为 7 -> 触发合成 D

总结:对于 A + B + C -> D 这种多对一的合成:

  • 业务逻辑清晰、可读性高: 用 方案一(EnumSet),这也是最标准的面向对象写法。
  • 高并发、或者要存数据库高性能持久化: 用 方案二(Bitmask位运算),数据库只需要存一个 int 字段即可代表 A/B/C 的任意组合完成状态。
http://www.jsqmd.com/news/843693/

相关文章:

  • 挂耳式耳机哪个听音乐好?2026音质最好的开放式耳机前十推荐
  • 猫抓浏览器扩展完全指南:5步掌握网页视频资源嗅探与下载
  • 从入门到精通:wrk压力测试实战与性能调优全攻略
  • 从‘私密’到‘公开’:详解虚幻蓝图变量细节面板,让你的游戏设计更灵活(UE5.2)
  • 如何在Blender中完美导入导出3MF格式?终极指南带你轻松掌握3D打印文件处理
  • 别再折腾破解了!Docker Compose一键部署Confluence 8.x(附MySQL 8.0配置与数据持久化指南)
  • 在线客服系统源码
  • 别再只盯着X16了!深入聊聊M.2、Mini-PCIE这些‘变种’接口的电路设计异同与选型指南
  • 基于μC/OS-II与DSP的备自投装置嵌入式实时系统设计
  • Keil MDK中HEX文件未生成的8.3路径问题解析
  • 产业园区如何构建智能化科技服务体系?
  • 母婴除菌洗碗机测评:慧曼守护宝宝入口健康 - 服务品牌热点
  • RVC-WebUI语音克隆工具:从零开始的完整使用指南
  • 全志T113-S3 USB两步烧录实战:从FEL模式到固件部署
  • JetBrains IDE试用重置插件:30秒解决开发工具到期烦恼
  • Windows系统优化利器:DriverStore Explorer技术全解析与实战指南
  • 终极指南:如何用开源温度控制中心彻底释放Dell G15性能潜力
  • 英雄联盟资料自定义终极指南:3分钟学会LeaguePrank完整使用教程
  • 别再乱用%pre脚本了!手把手教你正确编写RPM spec文件的升级逻辑(避坑rpm.lock锁定)
  • 老根家具居然能传三代?
  • AzurLaneAutoScript:解放双手的碧蓝航线全自动助手终极指南
  • 告别官方Demo:用QT从零封装Vector 1610 CAN驱动(附完整代码)
  • HoRain云--FastAPI响应状态码设置全攻略
  • DownKyi完整使用教程:免费B站视频下载终极解决方案
  • 对抗资本收割的价值投资
  • 微信小程序语音播报插件WechatSI保姆级教程(含长文本分段播放避坑指南)
  • 空间转录组 | 芯片升级,更高的捕获率,更低的价格!
  • 架构解析:WinFlexBison如何实现Windows平台上的专业词法语法分析解决方案
  • 正规 PCB 电路板生产厂家,大小订单均可承接
  • 对抗资本收割的认知重塑