【仿真建模-anylogic】Statechart原理解析

复制代码
Author:赵志乾
Date:2024-06-15
Declaration:All Right Reserved!!!

1. 类图

2. 原理解析

2.1 核心函数

Statechart的核心函数如下:

|--------------------------------------|------------------------------------------------|
| 函数 | 功能 |
| Statechart(Agent owner, short maxat) | 构造函数,入参指定状态图owner以及允许的最大激活Transition个数 |
| void start() | 启动函数,激活状态图并执行Entry Action |
| void fireEvent(Object msg) | 将消息加入状态图的消息队列,该消息会被立即消费或经过若干个不耗时的执行步后被消费,否则被丢弃 |
| boolean receiveMessage(Object msg) | 将消息传递至状态图,要么立即执行,要么被丢弃; |

2.2 代码解析

Anylogic内核做了代码混淆,以下代码为二次加工后的逻辑;

复制代码
//************************核心字段************************
// 状态图所属的Agent    
private transient Agent owner;
// 当前激活的状态
private T activeState = null;
// 当前激活的转换容器
protected Transition[] activeTransitions;
// 当前激活的转换个数
protected int activeTransitionSize = 0;
// 状态图待处理的消息队列
private LinkedList<Object> msgQueue;
// 备份的当前时间
private double currentTime = Double.NEGATIVE_INFINITY;
	
//************************构造函数*************************
// 指定状态图所属的Agent以及状态图允许同时处于激活状态的最大转换数
public Statechart(Agent owner, short maxConcurrentActived) {
    this.owner = owner;
    this.activeTransitions = new Transition[maxConcurrentActived];
    this.activeTransitionSize = 0;
    this.msgQueue = new LinkedList<>();
}

//***********************状态图启动*************************
// 状态图启动函数在owner的start()函数中调用
public void start() {
    // 校验:已启动的状态图不允许再次调用start()
    if (this.activeState != null) {
        this.g.error(this.getFullName() + jj.hdg);
    }
    // 执行自定义逻辑,之后进入首个状态
    this.owner.executeActionOf(this);
}

//************************事件处理**************************
// 无排队:收到事件消息能处理则处理,否则直接丢弃;
public boolean receiveMessage(Object msg) {
    boolean result = false;
    // 遍历当前激活状态的消息转换,并尝试执行转换
    for(int index = 0; index < this.activeTransitionSize ; ++index) {
       Transition transition = this.activeTransitions[index];
       if (transition instanceof TransitionMessage && ((TransitionMessage)transition).f(msg)) {
            //此处仅仅标记结果为成功,并未结束循环;所以当消息匹配多个激活的转换时,这个几个转换将会各自独立执行
            result = true;
        }
     }

     return result;
}

// 有排队:收到事件消息优先进队列,然后尝试消费一次
public void fireEvent(Object msg) {
    double currentTime = this.getAgent().time();
    if (this.currentTime < currentTime) {
        this.msgQueue.clear();
    }

    this.msgQueue.addLast(msg);
    this.currentTime = currentTime;
    this.tryConsume();
}

//*************************转换的激活与取消激活**************************************
// 激活转换:激活转换时,尝试进行一次消费
void activateTransition(Transition transition) {
    this.activeTransition[this.activeTransitionSize++] = transition;
    this.tryConsume();
}
// 取消激活转换
void deactivateTransition(Transition transition) {
    // 找到取消激活的转换所对应的下标
    int index;
    for(index = 0; index< activeTransitionSize; index++){
        if(this.activeTransitions[index] == transition){
			break;
		}
	}
	// 合法性校验:只有激活状态的转换才允许取消激活
	if(index >= this.activeTransitionSize){
		throw new RuntimeException("INTERNAL ERROR: a statechart transition being deactivated is not active");
	}
	// 将之后的元素逐个向前移动
    for(; index<activeTransitionSize-1; index++){
	    this.activeTransitions[index] = this.activeTransitions[index+1];
	}
    // 修正激活转换个数
	this.activeTransitionSize--;
}

//****************************变更*************************************
public void onChange() {
    // 变更发生时,刷新TransitionRate和TransitionCondition的触发条件
    for(int index = 0; index < this.activeTransitionSize; ++index) {
        Transition transition = this.activeTransitions[var1];
        if (transition instanceof TransitionRate) {
            ((TransitionRate)transition).g();
        } else if (transition instanceof TransitionCondition) {
            ((TransitionCondition)transition).g();
        }
    }
}

//*************************尝试消费************************************
private void tryConsume() {
    //清除历史消息
    if (this.getAgent().time() > this.currentTime) {
        this.msgQueue.clear();
        return;
    }
    //尝试消费消息
    int index = 0;
    for(Iterator iterator = this.msgQueue.iterator(); iterator.hasNext(); ++index) {
        Object msg = iterator.next();
        if (this.receiveMessage(msg)) {
            break;
         }
     }
     //消费成功
     if (index < this.msgQueue.size()) {
         //移除成功消费消息及其之前的消息
         for(int cycle = 0; cycle <= index; ++cycle) {
            this.msgQueue.removeFirst();
         }
     }
}

3. 应用场景

Statechart主要用于对事件驱动或时间驱动的行为进行建模,其包含状态和转换两种核心元素;转换可由消息、超时、速率、条件等触发,从而导致状态发生流转;

实际使用中有两种方式向状态图发送消息:fireEvent和receiveMessage,两者的区别在于消息是否会被加入队列进行排队;可根据实际应用场景进行选择;

相关推荐
2601_962106644 小时前
【Java Set综合实战】商品管理系统 + 图书收藏系统|Product、Book自定义类全套代码
java
RuoyiOffice4 小时前
SpringBoot+Vue3 凭证生命周期设计:审核、过账、冲销与反过账怎样保持账目一致
java·spring boot·事务·springboot3·财务系统·会计凭证·ruoyi office
2601_962106645 小时前
HashMap入门|工号-姓名键值存储、两种遍历方式、根据key/value查
java
杨凯凡5 小时前
Spring Framework 7 API 版本管理实战:请求头路由、兼容迁移与废弃策略
java·rest api·springframework·spring boot 4·api版本管理
T_Wizard6 小时前
同一个问题写了 4 遍:官方 SDK / HTTP / Spring AI / LangChain4j,到底该选哪个
java·ai编程
hai_android6 小时前
AudioTrack 深度解析:从原理到实战
android·java·kotlin
斯维赤6 小时前
限流、熔断、降级,你真的分得清吗?
java·后端·架构
aiks_yuan9 小时前
Java CPU 100% 怎么排查:JDK 11 起 jstack 自带线程 CPU 时间,不用再 top -H 换算十六进制(JDK 8、11、17 实测)
java
Flynn Liang10 小时前
AiServices 源码级拆解:一个接口如何变成 RAG Agent
java·langchain·源码分析·rag·langchain4j·aiservices
Flynn Liang11 小时前
LangChain4j 1.23 架构全景:Java 大模型应用的 6 层抽象
java·langchain·大模型·rag·ai agent·langchain4j