如何阻止Spring State Machine并行执行动作?配置与机制咨询
Spring State Machine 动作并行执行的控制方案
一、并行执行的触发逻辑
Spring State Machine里动作跑到并行线程执行,主要是这两种场景:
- 正交区域(Orthogonal Regions):当状态机配置了正交多区域时,默认会启动多个线程并行处理每个区域的状态转换动作。
- 异步配置触发:如果动作方法加了
@Async注解,或者状态机全局配置了异步任务执行器,又或者转换时显式指定了.async(),动作都会在新线程里执行。
二、阻止并行执行的有效方法
你试过的regionExecutionPolicy(RegionExecutionPolicy.SEQUENTIAL)没生效,大概率是配置场景不对或者位置错了,试试下面这些方案:
1. 针对正交区域的顺序执行配置
这个配置只对正交区域生效,而且要放在正确的层级:
如果是全局所有正交区域都要顺序执行,就在withConfiguration()下设置:
@Bean public StateMachine<States, Events> stateMachine(StateMachineConfigurer<States, Events> configurer) throws Exception { return configurer .withConfiguration() .regionExecutionPolicy(RegionExecutionPolicy.SEQUENTIAL) // 全局正交区域顺序执行 .and() .withStates() .initial(States.INIT) .orthogonal() // 正交区域定义 .region() .initial(States.SUB1_INIT) .state(States.SUB1_DONE) .and() .region() .initial(States.SUB2_INIT) .state(States.SUB2_DONE) .and() .and() .build(); }
如果只是某个局部正交区域要顺序执行,就在对应区域的配置里单独设置:
.orthogonal() .region() .initial(States.SUB1_INIT) .state(States.SUB1_DONE) .and() .region() .executionPolicy(RegionExecutionPolicy.SEQUENTIAL) // 局部区域顺序执行 .initial(States.SUB2_INIT) .state(States.SUB2_DONE) .and()
2. 强制所有动作同步执行
直接给状态机配置同步任务执行器,不管什么场景,动作都在触发事件的线程里跑:
@Bean public StateMachine<States, Events> stateMachine(StateMachineConfigurer<States, Events> configurer) throws Exception { return configurer .withConfiguration() .taskExecutor(new SyncTaskExecutor()) // Spring自带的同步执行器,无新线程 .and() // 你的状态、转换配置 .build(); }
也可以自定义同步执行器:
@Bean public TaskExecutor syncTaskExecutor() { SyncTaskExecutor executor = new SyncTaskExecutor(); executor.setThreadNamePrefix("sync-sms-"); return executor; } @Bean public StateMachine<States, Events> stateMachine(StateMachineConfigurer<States, Events> configurer, TaskExecutor syncTaskExecutor) throws Exception { return configurer .withConfiguration() .taskExecutor(syncTaskExecutor) .and() // 其他配置 .build(); }
3. 清理异步相关配置
- 检查所有动作方法,去掉
@Async注解; - 检查转换配置,删掉
.async()声明:
// 把带async的转换改成同步 .transition() .source(States.INIT) .target(States.WORKING) .event(Events.START) // .async() 删掉这一行 .action(workingAction)
三、新版本替代旧版自定义Executor的方案
旧版的自定义Executor选项被移除后,新版本统一通过taskExecutor()方法配置执行器。上面的同步执行器配置就是替代方案,你可以根据需求选择同步或自定义异步执行器,但如果要阻止并行,选SyncTaskExecutor即可。
四、排查regionExecutionPolicy未生效的常见原因
- 没用到正交区域:这个配置只对多区域的正交状态生效,单区域状态机用了也没用;
- 配置层级错误:必须在
withConfiguration()(全局)或对应区域的配置块里设置,放错位置不会生效; - 版本问题:确认你的Spring State Machine版本是2.x及以上,更早的版本可能不支持这个配置项。
内容的提问来源于stack exchange,提问作者Maayan Hope
相关产品推荐
相关产品推荐

