并发状态机会影响子状态的调用次数

45 views
Skip to first unread message

Momo Cuki

unread,
Jul 13, 2021, 6:13:24 AM7/13/21
to squirrel state machine
为什么我测试下来,并发状态机会影响调用的次数,发送一次事件,结果转换方法被调用好多次。

 测试结果 如下:
开始测试状态机事件
开始进入停止状态
onSuspendService from=InitRobot to=SuspendService   event=initerror.event
开始进入初始北状态
onInitRobot from=SuspendService to=InitRobot   event=reset.event
去掉并发状态,同时启动水位、广告、主 状态机
onRobot from=InitRobot to=Robot   event=initcomplete.event
开始进入低水位状态
onLowWater from=NormalWater to=LowWater   event=lowwater.event
开始进入播放广告状态
onPlayAd from=IdleAd to=PlayAd   event=havead.event
开始进入暂停播放广告状态
onPauseAd from=PlayAd to=PauseAd   event=pausead.event
开始进入服务状态
onInService from=InIdle to=InService   event=inservice.event
开始进入下班状态
onWorkOff from=InService to=WorkOff   event=workoff.event
开始进入播放广告状态
onPlayAd from=PauseAd to=PlayAd   event=palyad.event
开始进入暂停状态
onPauseService from=Work to=PauseService   event=work2pauseservice.event
onPauseService from=Work to=PauseService   event=work2pauseservice.event
onPauseService from=Work to=PauseService   event=work2pauseservice.event
开始进入无广告状态
onIdleAd from=PlayAd to=IdleAd   event=noad.event
开始进入正常水位状态
onNormalWater from=LowWater to=NormalWater   event=normalwater.event
开始进入高水位状态
onHighWater from=NormalWater to=HighWater   event=highwater.event
开始进入恢复暂停状态
onWork from=PauseService to=Work   event=pauseservice.event
onWork from=PauseService to=Work   event=pauseservice.event
onWork from=PauseService to=Work   event=pauseservice.event
开始进入回充状态
onGoCharge from=WorkOff to=GoCharge   event=homecharge.event
onGoCharge from=WorkOff to=GoCharge   event=homecharge.event
onGoCharge from=WorkOff to=GoCharge   event=homecharge.event
onGoCharge from=WorkOff to=GoCharge   event=homecharge.event
开始进入空闲状态
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=GoCharge to=InIdle   event=inidle.event
onInIdle from=GoCharge to=InIdle   event=inidle.event
onInIdle from=GoCharge to=InIdle   event=inidle.event
onInIdle from=GoCharge to=InIdle   event=inidle.event
开始进入正常水位状态
onNormalWater from=HighWater to=NormalWater   event=normalwater.event
开始进入服务状态
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
onInService from=InIdle to=InService   event=inservice.event
开始进入下班状态
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
onWorkOff from=InService to=WorkOff   event=workoff.event
开始进入空闲状态
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=GoCharge to=InIdle   event=inidle.event
onInIdle from=GoCharge to=InIdle   event=inidle.event
onInIdle from=GoCharge to=InIdle   event=inidle.event
onInIdle from=GoCharge to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=Work to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
onInIdle from=WorkOff to=InIdle   event=inidle.event
Class transformation time: 0.02639393s for 963 classes or 2.7408026998961578E-5s per class



主函数 
InputStream is = new FileInputStream(xmlFile);
UntypedStateMachineBuilder xmlbuilder = new UntypedStateMachineImporter().importDefinition(is);
RobotStateMachine stateMachine1 = xmlbuilder.newAnyStateMachine(RobotStateMachine.RobotState.InitRobot, StateMachineConfiguration.create().enableDebugMode(false));

stateMachine1.addTransitionCompleteListener(new RobotStateMachine.TransitionCompleteListener<RobotStateMachine, RobotStateMachine.RobotState, String, Void>() {
@Override
public void transitionComplete(StateMachine.TransitionCompleteEvent<RobotStateMachine, RobotStateMachine.RobotState, String, Void> event) {
// System.out.println("StateMachine = " + event.getSourceState()+"--["+event.getCause()+"]--"+event.getTargetState());
}


});

stateMachine1.start();
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getPath());
System.out.println("开始测试状态机事件");

System.out.println("开始进入停止状态");
stateMachine1.fire("initerror.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getPath());
System.out.println("开始进入初始北状态");
stateMachine1.fire("reset.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getPath());
System.out.println("去掉并发状态,同时启动水位、广告、主 状态机");
stateMachine1.fire("initcomplete.event");
// stateMachine1.fire("inidle.event");
// System.out.println("当前状态"+ stateMachine1.getSubStatesOn(RobotStateMachine.RobotState.Robot));
System.out.println("开始进入低水位状态");
stateMachine1.fire("lowwater.event");
// System.out.println("当前状态===="+ stateMachine1.getLastRawState().getThis().getPath());
System.out.println("开始进入播放广告状态");
stateMachine1.fire("havead.event");
// System.out.println("当前状态"+ stateMachine1.getSubStatesOn(RobotStateMachine.RobotState.AdSm));
System.out.println("开始进入暂停播放广告状态");
stateMachine1.fire("pausead.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入服务状态");
stateMachine1.fire("inservice.event");
// System.out.println("当前状态"+ stateMachine1.getSubStatesOn(RobotStateMachine.RobotState.Main));
System.out.println("开始进入下班状态");
stateMachine1.fire("workoff.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入播放广告状态");
stateMachine1.fire("palyad.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());

System.out.println("开始进入暂停状态");
stateMachine1.fire("work2pauseservice.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入无广告状态");
stateMachine1.fire("noad.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入正常水位状态");
stateMachine1.fire("normalwater.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入高水位状态");
stateMachine1.fire("highwater.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入恢复暂停状态");
stateMachine1.fire("pauseservice.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入回充状态");
stateMachine1.fire("homecharge.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入空闲状态");
stateMachine1.fire("inidle.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入正常水位状态");
stateMachine1.fire("normalwater.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());

System.out.println("开始进入服务状态");
stateMachine1.fire("inservice.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入下班状态");
stateMachine1.fire("workoff.event");
// System.out.println("当前状态"+ stateMachine1.getCurrentRawState().getStateId());
System.out.println("开始进入空闲状态");
stateMachine1.fire("inidle.event");


状态机实现

public class RobotStateMachine extends AbstractStateMachine<RobotStateMachine, RobotState, String, Void> {

private StringBuilder logger = new StringBuilder();

void postConstruct() {
System.out.println("RobotStateMachine PostConstruct Touched!");
}

public enum RobotState {
InitRobot, Robot, WaterLevelsm, LowWater, NormalWater, HighWater, AdSm, IdleAd,
PlayAd, PauseAd, Main, Work, InIdle, InService, WorkOff, GoCharge, PauseService, SuspendService,
root, robotsm,
s1, s11, s12, s2, s21, s22, s3, s31, s32, s33, s4, s41, s42, s43, state1, state11, state12 , state2, state21, state22, state3, state31, state32, state33, state4, state41, state42, state43
}

protected void onRobot(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onRobot");
System.out.println("onRobot from="+from+" to="+to + " event=" + event);
}

protected void onNormalWater(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onNormalWater");
System.out.println("onNormalWater from="+from+" to="+to + " event=" + event);
}

protected void onLowWater(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onLowWater");
System.out.println("onLowWater from="+from+" to="+to + " event=" + event);
}

protected void onHighWater(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onHighWater");
System.out.println("onHighWater from="+from+" to="+to + " event=" + event);
}

protected void onIdleAd(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onIdleAd");
System.out.println("onIdleAd from="+from+" to="+to + " event=" + event);
}

protected void onPlayAd(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onPlayAd");
System.out.println("onPlayAd from="+from+" to="+to + " event=" + event);
}


protected void onPauseAd(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onPauseAd");
System.out.println("onPauseAd from="+from+" to="+to + " event=" + event);
}

protected void onInIdle(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onInIdle");
System.out.println("onInIdle from="+from+" to="+to + " event=" + event);
}


protected void onInService(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onInService");
System.out.println("onInService from="+from+" to="+to + " event=" + event);
}


protected void onWorkOff(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onWorkOff");
System.out.println("onWorkOff from="+from+" to="+to + " event=" + event);
}


protected void onGoCharge(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onGoCharge");
System.out.println("onGoCharge from="+from+" to="+to + " event=" + event );
}


protected void onPauseService(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onPauseService");
System.out.println("onPauseService from="+from+" to="+to + " event=" + event);
}

protected void onWork(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onWork");
System.out.println("onWork from="+from+" to="+to + " event=" + event);
}

protected void onSuspendService(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onSuspendService");
System.out.println("onSuspendService from="+from+" to="+to + " event=" + event);
}

protected void onInitRobot(RobotState from, RobotState to, String event){
addOptionalDot();
logger.append("onInitRobot");
System.out.println("onInitRobot from="+from+" to="+to + " event=" + event);
}

private void addOptionalDot() {
if (logger.length() > 0) {
logger.append('.');
}
}

public String consumeLog() {
final String result = logger.toString();
logger = new StringBuilder();
return result;
}


}

状态机XML文件

<?
xml version="1.0" encoding="utf-8"?>
<scxml version="1.0"
initial="InitRobot"
xmlns="http://www.w3.org/2005/07/scxml"
xmlns:sqrl="http://squirrelframework.org/squirrel">

<sqrl:fsm context-insensitive="true"
context-type="java.lang.Object"
event-type="java.lang.String"
fsm-type="com.mkl.modulecore.initrobot.statemachine.RobotStateMachine"
id="wKDMXvUmTS"
state-type="com.mkl.modulecore.initrobot.statemachine.RobotStateMachine$RobotState"/>
<!--初始化状态-->
<state id="InitRobot">
<onentry/>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="initcomplete.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="Robot" >
<sqrl:action content="method#onRobot:0"/>
</transition>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="initerror.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="SuspendService" >
<sqrl:action content="method#onSuspendService:0"/>
</transition>
<onexit/>
</state>


<!--并发状态机-->
<!-- 工作状态-->
<parallel id="Robot">

<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="roboterror.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="SuspendService" >
<sqrl:action content="method#onSuspendService:0"/>
</transition>
<state id="WaterLevelsm" initial="NormalWater">
<!-- <history type="deep"/>-->
<!-- state machine for "waterlevel" (low_water/normal_water/high_water) -->
<state id="LowWater">
<onentry>
<!-- <sqrl:action content="method#entryLowWater:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="normalwater.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="NormalWater" >
<sqrl:action content="method#onNormalWater:0"/>
</transition>
<onexit/>
</state>

<state id="NormalWater">
<onentry>
<!-- <sqrl:action content="method#entryNormalWater:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="lowwater.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="LowWater" >
<sqrl:action content="method#onLowWater:0"/>
</transition>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="highwater.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="HighWater" >
<sqrl:action content="method#onHighWater:0"/>
</transition>
<onexit/>
</state>

<state id="HighWater">
<onentry>
<!-- <sqrl:action content="method#entryHighWater:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="normalwater.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="NormalWater" >
<sqrl:action content="method#onNormalWater:0"/>
</transition>
<onexit/>
</state>
</state>

<state id="AdSm" initial="IdleAd">
<!-- <history type="deep"/>-->
<!-- state machine for "adsm" (IdleAd /PlayAd / PauseAd) -->
<state id="IdleAd">
<onentry>
<!-- <sqrl:action content="method#entryIdleAd:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="havead.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="PlayAd" >
<sqrl:action content="method#onPlayAd:0"/>
</transition>
<onexit/>
</state>

<state id="PlayAd">
<onentry>
<!-- <sqrl:action content="method#entryPlayAd:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="noad.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="IdleAd" >
<sqrl:action content="method#onIdleAd:0"/>
</transition>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="pausead.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="PauseAd" >
<sqrl:action content="method#onPauseAd:0"/>
</transition>
<onexit/>
</state>


<state id="PauseAd">
<onentry>
<!-- <sqrl:action content="method#entryPauseAd:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="palyad.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="PlayAd" >
<sqrl:action content="method#onPlayAd:0"/>
</transition>
<onexit/>
</state>

</state>


<state id="Main" initial="Work">

<!-- This time we reference a state
defined in an external file. -->
<!-- <xi:include href="2.xml" parse="text"/>-->
<state id="Work" initial="InIdle">
<history type="deep"/>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="work2pauseservice.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="PauseService" >
<sqrl:action content="method#onPauseService:0"/>
</transition>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="inidle.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="InIdle" >
<sqrl:action content="method#onInIdle:0"/>
</transition>
<state id="InIdle">
<onentry>
<!-- <sqrl:action content="method#entryInIdle:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="inservice.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="InService" >
<sqrl:action content="method#onInService:0"/>
</transition>
<onexit/>
</state>

<state id="InService">
<onentry>
<!-- <sqrl:action content="method#entryInService:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="workoff.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="WorkOff" >
<sqrl:action content="method#onWorkOff:0"/>
</transition>
<!-- <transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="pauseservice.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="pauseservice" />-->
<onexit/>
</state>

<state id="WorkOff">
<onentry>
<!-- <sqrl:action content="method#entryWorkOff:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="homecharge.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="GoCharge" >
<sqrl:action content="method#onGoCharge:0"/>
</transition>

<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="inidle.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="InIdle" >
<sqrl:action content="method#onInIdle:0"/>
</transition>
</state>

<state id="GoCharge">
<onentry>
<!-- <sqrl:action content="method#entryGoCharge:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="inidle.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="InIdle" >
<sqrl:action content="method#onInIdle:0"/>
</transition>
</state>
</state>
<state id="PauseService">
<onentry>
<!-- <sqrl:action content="method#entryPauseService:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="pauseservice.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="Work" >
<sqrl:action content="method#onWork:0"/>
</transition>
</state>
</state>
</parallel>

<!-- 停止状态-->
<state id="SuspendService">
<onentry>
<!-- <sqrl:action content="method#entrySupendService:0"/>-->
</onentry>
<transition cond="instance#org.squirrelframework.foundation.fsm.Conditions$Always" event="reset.event" sqrl:priority="1" sqrl:type="EXTERNAL" target="InitRobot" >
<sqrl:action content="method#onInitRobot:0"/>
</transition>
</state>


</scxml>
Reply all
Reply to author
Forward
0 new messages