【问题标题】:spring state machine in multi threaded environment多线程环境中的弹簧状态机
【发布时间】:2016-05-06 08:30:15
【问题描述】:

我们刚刚开始使用弹簧状态机。有几个问题:

  • 每个状态机的状态上下文是否只有一次?
  • 传递给状态机的事件是否以阻塞方式运行?有什么方法可以让它们并行运行,比如每次触发事件时提供一个新的状态机?

这是我的代码:

配置状态和转换:

@Override
public void configure(
        StateMachineTransitionConfigurer<WorkFlowStates, WorkFlowEvent> transitions)
                throws Exception {
    transitions
    .withExternal()
    .source(WorkFlowStates.ready)
    .target(WorkFlowStates.l1Creation)
    .event(WorkFlowEvent.createWorkItem)
    .action(workFlowCreator.createL1())

在状态转换期间提供操作:

public Action<WorkFlowStates, WorkFlowEvent> createL3() {
    return new Action<WorkFlowStates, WorkFlowEvent>() {

        public void execute(StateContext<WorkFlowStates, WorkFlowEvent> context) {
            System.out.println("l3 creation in action");
            Map<Object, Object> variables = context.getExtendedState().getVariables();
            Integer counter = (Integer)variables.get("counter");
            if(counter == null) counter = 1;
            else counter = counter+1;
            variables.put("counter", counter);
            System.out.println("Counter is "+counter);
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            variables.put(Level.l3, WorkItemFactory.createFailureL1L2L3WorkItem());
            variables.put("level", Level.l3);
            System.out.println("l3 created");
        }
    };
}

任务执行者:

public void configure(StateMachineConfigurationConfigurer<WorkFlowStates, 
WorkFlowEvent>config)
                throws Exception {
    config
    .withConfiguration()
    .autoStartup(true)
    .taskExecutor(taskExecutor())
    .listener(new WorkFlowStateMachineListener()); 
}

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

以及传递给状态机的事件:

StateMachine<WorkFlowStates, WorkFlowEvent> stateMachine = 
    context.getBean(StateMachine.class);

    stateMachine.sendEvent(WorkFlowEvent.createWorkItem);
    stateMachine.sendEvent(WorkFlowEvent.createWorkItem);

【问题讨论】:

    标签: java spring multithreading spring-statemachine


    【解决方案1】:

    是的,默认行为是阻塞的,因为底层 TaskExecutorSyncTaskExecutor。这可以通过common config 更改,如文档中所述。另请参阅tasks recipe,其中ThreadPoolTaskExecutor 默认用于并行执行区域。

    当远离阻塞机器时,您需要注意机器的工作方式以及它何时准备好处理进一步的事件,因为机器可能处于丢弃事件的状态。这通常是您可能需要开始添加延迟事件的时候,以便机器可以在将来更合适的时间处理这些事件。

    【讨论】:

    • 好的。对另一个问题的任何看法 - “状态上下文是否每个状态机只有一次?”
    • 啊,是的,人们通常会混淆这些上下文的含义。 StateContext 是每次转换创建的内容,StateMachineContext 是更高级别的上下文,通常在持久化机器时使用。所以不完全是“每台机器一次”。
    • 但是 ThreadPoolTask​​Executor 只有在我们有任务时才有用,对吧?当我只使用状态运行它时,它仍然处于阻塞状态。
    • 我认为您需要显示您的代码,因为这是使状态机执行异步的一种方式。可能你所做的并没有替换默认的SyncTaskExecutor
    • 当然。我已经用任务执行器更新了上面的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    相关资源
    最近更新 更多