状态机管理项目全过程

39 阅读2分钟

保证某个需求整体内部实现是有序的,其中包含状态定义、状态流转规则、并发控制、异常处理,下面以血透治疗为例子,完整方案实现

1️⃣ 定义状态

针对血透治疗,可以定义几个核心状态:

状态含义
PRE_TREATMENT(上机前)患者准备进入透析
IN_TREATMENT(治疗中)患者正在透析
POST_TREATMENT(下机后)透析完成
CANCELLED(取消)治疗取消或异常终止

2️⃣ 定义状态流转规则

保证状态只能按照业务逻辑流转:

  • PRE_TREATMENTIN_TREATMENT
  • IN_TREATMENTPOST_TREATMENT
  • 任意状态 → CANCELLED(异常或人工取消)

避免直接从 PRE_TREATMENT 跳到 POST_TREATMENT,保证流程完整性。

3️⃣ Java 枚举实现状态

public enum TreatmentStatus {
    PRE_TREATMENT,
    IN_TREATMENT,
    POST_TREATMENT,
    CANCELLED;
}

4️⃣ 流程控制类

保证整体流程能够做到有序

一般将状态码放到redis里面,如果需要判断这个状态码是不是原来的状态码,就去redis里面查找,如果已经更新的话,就不能在进行上机操作,说明状态已经流转,如果没有更新,则开始调用锁进行更新状态,保证状态锁能够一致。

public class TreatmentStateMachine {
​
    private TreatmentStatus currentStatus;
​
    public TreatmentStateMachine(TreatmentStatus initialStatus) {
        this.currentStatus = initialStatus;
    }
​
    public synchronized boolean transitionTo(TreatmentStatus nextStatus) {
        if (isValidTransition(currentStatus, nextStatus)) {
            currentStatus = nextStatus;
            return true;
        }
        return false; // 非法状态流转
    }
​
    private boolean isValidTransition(TreatmentStatus from, TreatmentStatus to) {
        switch (from) {
            case PRE_TREATMENT: return to == TreatmentStatus.IN_TREATMENT || to == TreatmentStatus.CANCELLED;
            case IN_TREATMENT: return to == TreatmentStatus.POST_TREATMENT || to == TreatmentStatus.CANCELLED;
            case POST_TREATMENT: return to == TreatmentStatus.CANCELLED;
            default: return false;
        }
    }
​
    public TreatmentStatus getCurrentStatus() {
        return currentStatus;
    }
}
​

这里用 synchronized 保证单个患者的状态操作线程安全

5️⃣ 并发与分布式处理

  1. 单患者多请求

    • 使用 Java 锁(synchronizedReentrantLock)保证状态变更原子性
  2. 多患者并发

    • 每个患者独立状态机,不需要全局锁
  3. 分布式场景

    • 使用 Redis 分布式锁或 Redisson 保证跨节点状态安全

6️⃣ 异常处理

  • 状态异常:非法状态流转 → 拒绝操作,记录日志
  • 流程中断:网络或系统异常 → 可回滚到上一个状态,或者设置 CANCELLED
  • 持久化状态:状态变更时同步写数据库,保证系统重启后状态一致