Spring 状态机 JOIN 的意外行为

问题描述 投票:0回答:1

我正在测试 Spring 状态机(版本 4.0.0)的一些功能。当我遇到 fork/join 功能时,JOIN 的行为对我来说有点奇怪(FORK 按我的预期工作)。任何解释将不胜感激。

基本上,我有一个状态机(分层状态机),如下所示: 从状态 I 开始,它创建 2 个正交区域(L 和 R)。每个区域包含 2 个状态(L1、L2 和 R1、R2)和 4 个来回更改状态的事件。 R2 和 L2 最后加入,然后导致最终状态 E

我的理解是,当L2和R2都处于活动状态时,导致JOIN的转换将被激活,然后最终到达E。

但是当我尝试模拟这个事件序列 [TIK、TOK、FUZ](转到 L2 然后返回 L1 并留在第一个区域中,然后转到第二个区域中的 R2)时,JOIN 转换被激活立即并最终到达 E,尽管当时 L2 未激活(L1 是激活的)。

  • 这是我在代码中的配置:

州:

 states.withStates()
                .initial(I)
                .fork(FORK)
                .state(LR)
                .join(JOIN)
                .state(E)
                .and().withStates().parent(LR)
                .region("R")
                        .initial(R1)
                        .state(R2)
                .and().withStates().parent(LR)
                .region("L")
                        .initial(L1)
                        .state(L2)

过渡:

transitions
                        .withExternal()          .source(I)            .target(FORK)              .event(S)
                .and()
                        .withFork()              .source(FORK)          .target(L1).target(R1)
                .and()
                        .withExternal()          .source(L1)            .target(L2)             .event(TIK)
                .and()
                        .withExternal()          .source(L2)            .target(L1)             .event(TOK)
                .and()
                        .withExternal()          .source(R1)            .target(R2)             .event(FUZ)
                .and()
                        .withExternal()          .source(R2)            .target(R1)             .event(BAZ)
                .and()
                        .withJoin()              .source(R2).source(L2) .target(JOIN)
                .and()
                        .withExternal()          .source(JOIN)             .target(E)

发送事件的代码:

log.info("Start sending events");
sm5.sendEvent(SM5Config.MEvent.S);
log.info("1. CURRENT STATE = {}", sm5.getState());
sm5.sendEvent(SM5Config.MEvent.TIK);
sm5.sendEvent(SM5Config.MEvent.TOK);
log.info("2. CURRENT STATE = {}", sm5.getState());
sm5.sendEvent(SM5Config.MEvent.FUZ);
log.info("3. CURRENT STATE = {}", sm5.getState());

还有日志(我添加了一些监听器日志)

Start sending events
================== State entered: LR
================== State entered: L1
================== State entered: R1
1. CURRENT STATE = RegionState [getIds()=[LR, L1, R1]...
================== State entered: L2
================== State entered: L1
2. CURRENT STATE = RegionState [getIds()=[LR, L1, R1]...
================== State entered: R2
================== State entered: E
3. CURRENT STATE = ObjectState [getIds()=[E]...

我不确定我的代码是错误的还是这是预期的行为。

PS:抱歉我的编辑/英语不好。

java state-machine fsm fork-join spring-statemachine
1个回答
0
投票

我想我在阅读下面的例子后找到了答案。这不是关于 Spring 状态机,而是关于一般状态机,但我想它也适用于 Spring 状态机。

Fork Join 示例

所以答案是:这是预期的行为。

它说:

触发事件X时,StateA1将退出并进入StateA2; Entry 和 doActivity 行为运行后,StateA2 的完成事件将被调度和调用。 然后启用并遍历从 StateA2 到 Join 伪状态的转换

我知道,当状态返回到 L1 时,从 L2(在我的问题中)到 JOIN 的转换已经完成。 JOIN 伪状态仅等待 R2 的转换到来(稍后)即可开始其工作。

因此,如果我想实现我在问题中所期望的行为,则需要对其进行稍微不同的设计。

仍然欢迎任何其他想法/评论。

© www.soinside.com 2019 - 2024. All rights reserved.