spring 多线程环境下的状态机
spring state machine in multi threaded environment
我们刚刚开始使用 spring 状态机。有几个问题:
- 每个状态机的状态上下文只有一次吗?
- 事件是否以阻塞方式传递给状态机运行?有什么方法可以使它们 运行 并行,比如每次触发事件时提供一个新的状态机?
这是我的代码:
配置状态和转换:
@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);
是的,默认行为是阻塞,因为底层 TaskExecutor
是 SyncTaskExecutor
。这可以通过 common config as mentioned in docs. Also see tasks recipe 更改,其中 ThreadPoolTaskExecutor
默认用于并行执行区域。
当远离阻塞机器时,您需要注意机器的工作方式以及它何时准备好处理进一步的事件,因为机器可能会处于事件被丢弃的状态。这通常是您可能需要开始添加延迟事件的时间,以便机器将来可以在更合适的时间处理这些事件。
我们刚刚开始使用 spring 状态机。有几个问题:
- 每个状态机的状态上下文只有一次吗?
- 事件是否以阻塞方式传递给状态机运行?有什么方法可以使它们 运行 并行,比如每次触发事件时提供一个新的状态机?
这是我的代码:
配置状态和转换:
@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);
是的,默认行为是阻塞,因为底层 TaskExecutor
是 SyncTaskExecutor
。这可以通过 common config as mentioned in docs. Also see tasks recipe 更改,其中 ThreadPoolTaskExecutor
默认用于并行执行区域。
当远离阻塞机器时,您需要注意机器的工作方式以及它何时准备好处理进一步的事件,因为机器可能会处于事件被丢弃的状态。这通常是您可能需要开始添加延迟事件的时间,以便机器将来可以在更合适的时间处理这些事件。