分支和连接:在弹簧状态机中并行执行两个区域的问题

时间:2019-03-21 12:23:44

标签: java fork-join spring-statemachine

我试图使用“ fork / join”结构在状态“ S2”的区域中并行执行状态机。状态机的配置基于uml model。 我对这两个区域的并行工作有疑问。 首先,状态机经过状态S20至S23,然后将状态从S30传递至S33。

问题出在哪里? 预先感谢您的帮助。

这是我的状态机配置:

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

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

    @Bean
    public StateMachineModelFactory<String, String> modelFactory() {
        Resource model = new ClassPathResource("/uml/simple-forkjoin.uml");
        return new UmlStateMachineModelFactory(model);
    }


     @Override public void configure(StateMachineConfigurationConfigurer<String, String> config) throws Exception {
     config
     .withConfiguration()
     .listener(new StateMachineListener())
     .autoStartup(true);
     }
}

表示状态的示例类:

@Slf4j
@WithStateMachine
public class S22 {


    @OnTransition(target = "S22")
    public void onTransition(StateContext<String, String> stateContext) {
        log.info(Colours.ANSI_BLUE + "target = \"S22\", getState().getId(): "
                + stateContext.getStateMachine().getState().getId()
                + Colours.ANSI_RESET);
        Sleep.sleep(1000);
    }

    @OnStateChanged(target = "S22")
    public void onStateChanged(StateContext<String, String> stateContext) {
        log.debug(Colours.B_HI_ANSI_GREEN + "S22 EXPECTS_ORDERS stateChanged :: Current state ID :: {}",
                stateContext.getStateMachine().getState().getId() + Colours.ANSI_RESET);
        Sleep.sleep(1000);
    }
}

日志:

2019-03-21 12:25:01.746  INFO 7648 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 8 ms
2019-03-21 12:25:01.780  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S0
2019-03-21 12:25:01.788  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S0          : target = "S0, getState().getId(): SI
2019-03-21 12:25:01.791 DEBUG 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S0          : S0 EXPECTS_ORDERS stateChanged :: Current state ID :: S0
2019-03-21 12:25:01.791  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : state changed from: SI to S0
2019-03-21 12:25:01.791  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S1
2019-03-21 12:25:01.792  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S1          : target = "S1", getState().getId(): S0
2019-03-21 12:25:01.794  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S21
2019-03-21 12:25:01.794  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S21         : target = "S21", getState().getId(): S2
2019-03-21 12:25:02.795  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S22
2019-03-21 12:25:02.797  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S22         : target = "S22", getState().getId(): S2
2019-03-21 12:25:03.799  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S23
2019-03-21 12:25:03.801  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S23         : target = "S23", getState().getId(): S2
2019-03-21 12:25:04.803  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : state changed from: S22 to S23
2019-03-21 12:25:04.803  INFO 7648 --- [nio-8080-exec-2] o.s.s.support.LifecycleObjectSupport     : started org.springframework.statemachine.support.DefaultStateMachineExecutor@76b2b847
2019-03-21 12:25:04.803  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : State machine started :: S2
2019-03-21 12:25:04.804  INFO 7648 --- [nio-8080-exec-2] o.s.s.support.LifecycleObjectSupport     : started S23 S22 S20 S21  / S23 / uuid=51391415-d1f5-440f-9c8e-677c00bcdd50 / id=null
2019-03-21 12:25:04.805 DEBUG 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S22         : S22 EXPECTS_ORDERS stateChanged :: Current state ID :: S2
2019-03-21 12:25:05.806  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : state changed from: S21 to S22
2019-03-21 12:25:05.806 DEBUG 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S21         : S21 EXPECTS_ORDERS stateChanged :: Current state ID :: S2
2019-03-21 12:25:06.807  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : state changed from: S20 to S21
2019-03-21 12:25:06.808 DEBUG 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S20         : S20 EXPECTS_ORDERS stateChanged :: Current state ID :: S2
2019-03-21 12:25:07.809  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : state changed from: null to S20
2019-03-21 12:25:07.809  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S31
2019-03-21 12:25:07.810  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S31         : target = "S31", getState().getId(): S2
2019-03-21 12:25:08.211  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S32
2019-03-21 12:25:08.212  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S32         : target = "S32", getState().getId(): S2
2019-03-21 12:25:08.613  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S33
2019-03-21 12:25:08.614  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S33         : target = "S33", getState().getId(): S2
2019-03-21 12:25:09.015  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S3
2019-03-21 12:25:09.016  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S3          : target = "S3", getState().getId(): S2
2019-03-21 12:25:09.016  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : transition started! target state: S3
2019-03-21 12:25:09.017  INFO 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S3          : target = "S3", getState().getId(): S2
2019-03-21 12:25:09.018  INFO 7648 --- [nio-8080-exec-2] o.s.s.support.LifecycleObjectSupport     : stopped org.springframework.statemachine.support.DefaultStateMachineExecutor@76b2b847
2019-03-21 12:25:09.018  INFO 7648 --- [nio-8080-exec-2] o.s.s.support.LifecycleObjectSupport     : stopped S23 S22 S20 S21  /  / uuid=51391415-d1f5-440f-9c8e-677c00bcdd50 / id=null
2019-03-21 12:25:09.019 DEBUG 7648 --- [nio-8080-exec-2] com.fj.forkJointest.forkJoin.S4          : S4 EXPECTS_ORDERS stateChanged :: Current state ID :: S4
2019-03-21 12:25:09.020  INFO 7648 --- [nio-8080-exec-2] c.f.f.config.StateMachineListener        : state changed from: S2 to S4

This is my github project

2 个答案:

答案 0 :(得分:0)

Spring State Machine使用TaskExecutor来执行区域,默认情况下它是同步的。要实现异步执行,您需要覆盖默认的任务执行器。

您可以通过以下几种方式进行操作:

使用StateMachineConfigurationConfigurer

@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,它将从SM中自动选择:

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

答案 1 :(得分:0)

执行器需要定义如下

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

状态机配置

.taskExecutor(myAsyncTaskExecutor()).taskScheduler(new ConcurrentTaskScheduler())