Spring状态机嵌套机器同步运行

时间:2016-01-19 17:04:18

标签: java spring state-machine spring-statemachine

我正在使用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运行的想法吗?

2 个答案:

答案 0 :(得分:0)

您没有显示完整配置,您的代码示例至少缺少taskExecutor。例如,执行fork / join的tasks示例正在使用ThreadPoolTaskExecutor。默认执行程序为SyncTaskExecutor。文档有一些注释如何配置。

https://github.com/spring-projects/spring-statemachine/blob/master/spring-statemachine-samples/tasks/src/main/java/demo/tasks/Application.java#L189

代码示例中的另一件事是您定义了零事件,这意味着您将无法drive一台机器。您已经定义了从READYFORK的转换而没有事件,这意味着它是无触发转换。当您启动状态机时,它会更改为其初始状态READY,匿名转换将其转换为FORK。此启动序列在启动期间发生,并且位于实际执行程序之外。

尝试使用事件定义从READYFORK的转换,然后在启动后将该事件发送到计算机并执行并行执行(假设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) {

}