我正在使用Spring State Machine并尝试配置一些嵌套功能。从本质上讲,我正在尝试将两个进程作为嵌套在一个状态中的单个机器运行。我有以下代码用于状态和转换:
public enum States {
READY, FORK, JOIN, TASKS, TERMINATE,
T1_INIT, C1_INIT, T1_READY, T1_POLL, T1_PROCESS, T1_STORE, T1_DELAY, C1_CONTINUE, T1_TERMINATE,
T2_INIT, C2_INIT, T2_READY, T2_POLL, T2_PROCESS, T2_STORE, T2_DELAY, C2_CONTINUE, T2_TERMINATE }
public enum Events {INITIALIZE, RUN, STOP, FALLBACK, CONTINUE, FIX, PROC_COMPLETE}
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.READY)
.fork(States.FORK)
.state(States.TASKS)
.join(States.JOIN)
.end(States.TERMINATE)
.and()
.withStates()
.parent(States.TASKS)
.initial(States.T1_INIT, initT1Action())
.state(States.T1_READY)
.state(States.T1_POLL, pollT1Action(), null)
.state(States.T1_PROCESS, processT1Action(), null)
.state(States.T1_STORE, storeT1Action(), null)
.state(States.T1_DELAY)
.choice(States.C1_CONTINUE)
.end(States.T1_TERMINATE)
.and()
.withStates()
.parent(States.TASKS)
.initial(States.T2_INIT, initT2Action())
.state(States.T2_READY)
.state(States.T2_POLL, pollT2Action(), null)
.state(States.T2_PROCESS, processT2Action(), null)
.state(States.T2_STORE, storeT2Action(), null)
.state(States.T2_DELAY)
.choice(States.C2_CONTINUE)
.end(States.T2_TERMINATE);
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.READY).target(States.FORK)
.and()
.withFork()
.source(States.FORK).target(States.TASKS)
.and()
.withExternal()
.source(States.T1_INIT).target(States.T1_READY)
.and()
.withExternal()
.source(States.T1_READY).target(States.T1_POLL)
.and()
.withExternal()
.source(States.T1_POLL).target(States.T1_PROCESS).guard(pollT1Guard())
.and()
.withExternal()
.source(States.T1_PROCESS).target(States.T1_STORE).guard(processT1Guard())
.and()
.withExternal()
.source(States.T1_STORE).target(States.T1_DELAY).guard(storeT1Guard())
.and()
.withExternal()
.source(States.T1_DELAY).target(States.C1_CONTINUE)
.and()
.withChoice()
.source(States.C1_CONTINUE)
.first(States.T1_POLL, continueChoiceT1Guard())
.last(States.T1_TERMINATE)
.and()
.withExternal()
.source(States.T2_INIT).target(States.T2_READY)
.and()
.withExternal()
.source(States.T2_READY).target(States.T2_POLL)
.and()
.withExternal()
.source(States.T2_POLL).target(States.T2_PROCESS).guard(pollT2Guard())
.and()
.withExternal()
.source(States.T2_PROCESS).target(States.T2_STORE).guard(processT2Guard())
.and()
.withExternal()
.source(States.T2_STORE).target(States.T2_DELAY).guard(storeT2Guard())
.and()
.withExternal()
.source(States.T2_DELAY).target(States.C2_CONTINUE)
.and()
.withChoice()
.source(States.C2_CONTINUE)
.first(States.T2_POLL, continueChoiceT2Guard())
.last(States.T2_TERMINATE)
.and()
.withJoin()
.source(States.TASKS).target(States.JOIN)
.and()
.withExternal()
.source(States.JOIN).target(States.TERMINATE);
}
我期待机器分叉在Task状态中识别的两台机器并将它们作为单独的机器运行。 T1和T2动作设置为在Task中的每个状态中有延迟。 T1延迟1秒,T2延迟半秒。
我发现T1会在所有状态之间运行,并在T2开始之前结束。有关使它们以fork / join运行的想法吗?
答案 0 :(得分:0)
您没有显示完整配置,您的代码示例至少缺少taskExecutor
。例如,执行fork / join的tasks
示例正在使用ThreadPoolTaskExecutor
。默认执行程序为SyncTaskExecutor
。文档有一些注释如何配置。
代码示例中的另一件事是您定义了零事件,这意味着您将无法drive
一台机器。您已经定义了从READY
到FORK
的转换而没有事件,这意味着它是无触发转换。当您启动状态机时,它会更改为其初始状态READY
,匿名转换将其转换为FORK
。此启动序列在启动期间发生,并且位于实际执行程序之外。
尝试使用事件定义从READY
到FORK
的转换,然后在启动后将该事件发送到计算机并执行并行执行(假设taskExecutor已正确设置)。
答案 1 :(得分:-1)
实际上,这里是整个FSM配置类的代码:
@Configuration
@EnableStateMachine
@WithStateMachine
public class FSMFactoryConfig extends EnumStateMachineConfigurerAdapter<States, Events> {
@Autowired
StateMachine<States, Events> stateMachine;
ArrayList<IDataProcessor> dp = new ArrayList<>();
private void createProcessors() {
dp.add(0, (IDataProcessor) new DataProcessor());
dp.add(1, (IDataProcessor) new DataProcessor2());
}
@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> config)
throws Exception {
createProcessors();
config
.withConfiguration()
.autoStartup(false)
.taskExecutor(taskExecutor())
.taskScheduler(new ConcurrentTaskScheduler())
.listener(new StateMachineEventListener());
}
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.READY)
.fork(States.FORK)
.state(States.TASKS)
.join(States.JOIN)
.end(States.TERMINATE)
.and()
.withStates()
.parent(States.TASKS)
.initial(States.T1_INIT, initT1Action())
.state(States.T1_READY)
.state(States.T1_POLL, pollT1Action(), null)
.state(States.T1_PROCESS, processT1Action(), null)
.state(States.T1_STORE, storeT1Action(), null)
.state(States.T1_DELAY)
.choice(States.C1_CONTINUE)
.end(States.T1_TERMINATE)
.and()
.withStates()
.parent(States.TASKS)
.initial(States.T2_INIT, initT2Action())
.state(States.T2_READY)
.state(States.T2_POLL, pollT2Action(), null)
.state(States.T2_PROCESS, processT2Action(), null)
.state(States.T2_STORE, storeT2Action(), null)
.state(States.T2_DELAY)
.choice(States.C2_CONTINUE)
.end(States.T2_TERMINATE);
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.READY).target(States.FORK)
.and()
.withFork()
.source(States.FORK).target(States.TASKS)
.and()
.withExternal()
.source(States.T1_INIT).target(States.T1_READY)
.and()
.withExternal()
.source(States.T1_READY).target(States.T1_POLL)
.and()
.withExternal()
.source(States.T1_POLL).target(States.T1_PROCESS).guard(pollT1Guard())
.and()
.withExternal()
.source(States.T1_PROCESS).target(States.T1_STORE).guard(processT1Guard())
.and()
.withExternal()
.source(States.T1_STORE).target(States.T1_DELAY).guard(storeT1Guard())
.and()
.withExternal()
.source(States.T1_DELAY).target(States.C1_CONTINUE)
.and()
.withChoice()
.source(States.C1_CONTINUE)
.first(States.T1_POLL, continueChoiceT1Guard())
.last(States.T1_TERMINATE)
.and()
.withExternal()
.source(States.T2_INIT).target(States.T2_READY)
.and()
.withExternal()
.source(States.T2_READY).target(States.T2_POLL)
.and()
.withExternal()
.source(States.T2_POLL).target(States.T2_PROCESS).guard(pollT2Guard())
.and()
.withExternal()
.source(States.T2_PROCESS).target(States.T2_STORE).guard(processT2Guard())
.and()
.withExternal()
.source(States.T2_STORE).target(States.T2_DELAY).guard(storeT2Guard())
.and()
.withExternal()
.source(States.T2_DELAY).target(States.C2_CONTINUE)
.and()
.withChoice()
.source(States.C2_CONTINUE)
.first(States.T2_POLL, continueChoiceT2Guard())
.last(States.T2_TERMINATE)
.and()
.withJoin()
.source(States.TASKS).target(States.JOIN)
.and()
.withExternal()
.source(States.JOIN).target(States.TERMINATE);
}
@Bean
public Guard<States, Events> initChoiceGuard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
System.out.println("in initChoiceGuard...");
return true;
}
};
}
int i1 = 0;
int i2 = 0;
@Bean
public Guard<States, Events> continueChoiceT1Guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
System.out.println("in continueChoiceT1Guard - count: " + i1);
return (i1++ < 5);
}
};
}
@Bean
public Guard<States, Events> continueChoiceT2Guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
System.out.println("in continueChoiceT2Guard - count: " + i2);
return (i2++ < 10);
}
};
}
@Bean
public Guard<States, Events> tasksChoiceGuard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
System.out.println("in tasksChoiceGuard");
return true;
}
};
}
@Bean
public Action<States, Events> initT1Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in initAction");
((IDataProcessor) dp.get(0)).init();
}
};
}
@Bean
public Action<States, Events> initT2Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in initAction");
((IDataProcessor) dp.get(1)).init();
}
};
}
@Bean
public Action<States, Events> pollT1Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in pollAction");
((IDataProcessor) dp.get(0)).poll();
}
};
}
@Bean
public Action<States, Events> pollT2Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in pollAction");
((IDataProcessor) dp.get(1)).poll();
}
};
}
@Bean
public Action<States, Events> processT1Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in pollAction");
((IDataProcessor) dp.get(0)).process();
}
};
}
@Bean
public Action<States, Events> processT2Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in pollAction");
((IDataProcessor) dp.get(1)).process();
}
};
}
@Bean
public Action<States, Events> storeT1Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in pollAction");
((IDataProcessor) dp.get(0)).store();
}
};
}
@Bean
public Action<States, Events> storeT2Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in pollAction");
((IDataProcessor) dp.get(1)).store();
}
};
}
@Bean
public Action<States, Events> resetT1Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in pollAction");
((IDataProcessor) dp.get(0)).reset();
}
};
}
@Bean
public Action<States, Events> resetT2Action() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in pollAction");
((IDataProcessor) dp.get(1)).reset();
}
};
}
@Bean
public Guard<States, Events> pollT1Guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
return ((IDataProcessor) dp.get(0)).pollComplete();
}
};
}
@Bean
public Guard<States, Events> pollT2Guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
return ((IDataProcessor) dp.get(1)).pollComplete();
}
};
}
@Bean
public Guard<States, Events> processT1Guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
return ((IDataProcessor) dp.get(0)).processComplete();
}
};
}
@Bean
public Guard<States, Events> processT2Guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
return ((IDataProcessor) dp.get(1)).processComplete();
}
};
}
@Bean
public Guard<States, Events> storeT1Guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
return ((IDataProcessor) dp.get(0)).storeComplete();
}
};
}
@Bean
public Guard<States, Events> storeT2Guard() {
return new Guard<States, Events>() {
@Override
public boolean evaluate(StateContext<States, Events> context) {
return ((IDataProcessor) dp.get(1)).storeComplete();
}
};
}
@Bean
public Action<States, Events> fixAction() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
System.out.println("in fixAction");
}
};
}
@Bean
public StateMachine<States, Events> stateMachine() {
return stateMachine;
}
@Bean(name = StateMachineSystemConstants.TASK_EXECUTOR_BEAN_NAME)
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor te = new ThreadPoolTaskExecutor();
te.setMaxPoolSize(50);
te.setThreadNamePrefix("LULExecutor-");
te.setCorePoolSize(25);
te.initialize();
return te;
}
//@StatesOnTransition(target = States.AUTOMATIC)
public void automaticFix(ExtendedState extendedState) {
}