在弹簧状态机的并行实例中异步执行子状态

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

我试图从一个uml模型创建一些状态机实例。我使用stateMachineFactory。我希望这些机器能够独立和异步地工作。

如果我只使用“基础”状态,一切都很好。机器实例可以独立地转到stateB和StateC。但是,当我使用区域和子状态(stateD)时,机器实例一个接一个地执行action(insideStateD1)。请看。

我发现状态是通过stateMachineTaskExecutor(默认为SyncTaskExecutor)执行的,但子状态是通过taskScheduler(默认为ConcurrentTaskScheduler)执行的。

这是配置:

@Configuration
@EnableStateMachineFactory
public class StateMachineConfig extends StateMachineConfigurerAdapter<String, String> {

    @Autowired
    StateMachineComponentResolver<String, String> stateMachineComponentResolver;

    @Bean
    public StateMachineModelFactory<String, String> modelFactory() {
        UmlStateMachineModelFactory umlStateMachineModelFactory = new UmlStateMachineModelFactory("classpath:uml/testSM1.uml");
        umlStateMachineModelFactory.setStateMachineComponentResolver(stateMachineComponentResolver);
        return umlStateMachineModelFactory;
    }

    @Override
    public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
        model
                .withModel()
                .factory(modelFactory());
    }

    @Override
    public void configure(StateMachineConfigurationConfigurer<String, String> config) throws Exception {
        config
                .withConfiguration()
               // .taskExecutor()  // I tried various taskExecutors
               // .taskScheduler() // I tried various taskSchedulers
                ;
    }
}

从同一模型实现许多状态机实例的正确方法是什么?

java spring spring-statemachine
1个回答
0
投票

可以通过StateMachineFactory获得SM的多个实例。

stateMachineFactory.getStateMachine(); //builds a new state machine

您在StateMachineConfig中创建的配置适用于所有SM实例。

Spring State Machine使用TaskExecutor进行区域执行(与顶级或嵌套区域无关),默认情况下它是同步的。要实现异步执行,您需要覆盖默认任务执行程序。这可以在配置中实现:

@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {
    config
        .withConfiguration()
            //other configs
            .taskExecutor(myAsyncTaskExecutor())
}

public TaskExecutor myAsyncTaskExecutor() {
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setCorePoolSize(5);
    return taskExecutor;
}

或者通过声明一个bean:

@Bean(name = StateMachineSystemConstants.TASK_EXECUTOR_BEAN_NAME)
public TaskExecutor taskExecutor() {
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setCorePoolSize(5);
    return taskExecutor;
}

TaskScheduler用于动作执行(与状态或转换相关的动作),而不用于子状态。

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