StateMachineFactory用于构建状态机拓扑。这个对象从语义上是不可改变的。如果你有一个StateMachineFactory对象,在API中没有改变他语义属性的操作。
参数<OPERAND> 状态机操作此对象类型。
<STATE> 实体的状态
<EVENTTYPE> 自理的外部事件类型
<EVENT> 事件对象
/**
* State machine topology. This object is semantically immutable. If you have a
* StateMachineFactory there's no operation in the API that changes its semantic
* properties.
*
* @param <OPERAND>
* The object type on which this state machine operates.
* @param <STATE>
* The state of the entity.
* @param <EVENTTYPE>
* The external eventType to be handled.
* @param <EVENT>
* The event object.
*
*/
@Public
@Evolving
final public class StateMachineFactory<OPERAND, STATE extends Enum<STATE>, EVENTTYPE extends Enum<EVENTTYPE>, EVENT> {
先讲用到的内部类。
TransitionsListNode定义了一链表,本次转换和下一个结点。
private class TransitionsListNode {
final ApplicableTransition<OPERAND, STATE, EVENTTYPE, EVENT> transition;
final TransitionsListNode next;
TransitionsListNode(
ApplicableTransition<OPERAND, STATE, EVENTTYPE, EVENT> transition,
TransitionsListNode next) {
this.transition = transition;
this.next = next;
}
}
ApplicableTransition是一个接口,有一个apply方法,如下所示:
private interface ApplicableTransition<OPERAND, STATE extends Enum<STATE>, EVENTTYPE extends Enum<EVENTTYPE>, EVENT> {
void apply(StateMachineFactory<OPERAND, STATE, EVENTTYPE, EVENT> subject);
}
Transition接口中定义了doTransition来定义State的转变。
private interface Transition<OPERAND, STATE extends Enum<STATE>, EVENTTYPE extends Enum<EVENTTYPE>, EVENT> {
STATE doTransition(OPERAND operand, STATE oldState, EVENT event,
EVENTTYPE eventType);
}
SingleInteralArc实现了Transition,有转换之后的状态postState和SingleArcTransition类型的转换,在SingleInternalArc中的doTransition方法返回了转换之后的状态。
private class SingleInternalArc implements
Transition<OPERAND, STATE, EVENTTYPE, EVENT> {
private STATE postState;
private SingleArcTransition<OPERAND, EVENT> hook; // transition hook
SingleInternalArc(STATE postState,
SingleArcTransition<OPERAND, EVENT> hook) {
this.postState = postState;
this.hook = hook;
}
@Override
public STATE doTransition(OPERAND operand, STATE oldState, EVENT event,
EVENTTYPE eventType) {
if (hook != null) {
hook.transition(operand, event);
}
return postState;
}
}
SingleArcTransition定义了转换的一个钩子,并且定义了事件,注意,它的返回类型是void.
/**
* Hook for Transition. This lead to state machine to move to
* the post state as registered in the state machine.
*/
@Public
@Evolving
public interface SingleArcTransition<OPERAND, EVENT> {
/**
* Transition hook.
*
* @param operand the entity attached to the FSM, whose internal
* state may change.
* @param event causal event
*/
public void transition(OPERAND operand, EVENT event);
}
MultipleArcTransition的transition是有返回类型的,
/**
* Hook for Transition.
* Post state is decided by Transition hook. Post state must be one of the
* valid post states registered in StateMachine.
*/
@Public
@Evolving
public interface MultipleArcTransition
<OPERAND, EVENT, STATE extends Enum<STATE>> {
/**
* Transition hook.
* @return the postState. Post state must be one of the
* valid post states registered in StateMachine.
* @param operand the entity attached to the FSM, whose internal
* state may change.
* @param event causal event
*/
public STATE transition(OPERAND operand, EVENT event);
}
如果多个事件类型共用一候hook,那么要分别调用多次。
/**
* @return a NEW StateMachineFactory just like {@code this} with the current
* transition added as a new legal transition
*
* Note that the returned StateMachineFactory is a distinct
* object.
*
* This method is part of the API.
*
* @param preState pre-transition state
* @param postState post-transition state
* @param eventTypes List of stimuli for the transitions
* @param hook transition hook
*/
public StateMachineFactory<OPERAND, STATE, EVENTTYPE, EVENT> addTransition(
STATE preState, STATE postState, Set<EVENTTYPE> eventTypes,
SingleArcTransition<OPERAND, EVENT> hook) {
StateMachineFactory<OPERAND, STATE, EVENTTYPE, EVENT> factory = null;
for (EVENTTYPE event : eventTypes) {
if (factory == null) {
factory = addTransition(preState, postState, event, hook);
} else {
factory = factory.addTransition(preState, postState, event, hook);
}
}
return factory;
}
如果转换之后,有多个postStates,則调用MultipleInternalArc。
/**
* @return a NEW StateMachineFactory just like {@code this} with the current
* transition added as a new legal transition
*
* Note that the returned StateMachineFactory is a distinct object.
*
* This method is part of the API.
*
* @param preState pre-transition state
* @param postStates valid post-transition states
* @param eventType stimulus for the transition
* @param hook transition hook
*/
public StateMachineFactory
<OPERAND, STATE, EVENTTYPE, EVENT>
addTransition(STATE preState, Set<STATE> postStates,
EVENTTYPE eventType,
MultipleArcTransition<OPERAND, EVENT, STATE> hook){
return new StateMachineFactory<OPERAND, STATE, EVENTTYPE, EVENT>
(this,
new ApplicableSingleOrMultipleTransition<OPERAND, STATE, EVENTTYPE, EVENT>
(preState, eventType, new MultipleInternalArc(postStates, hook)));
}
MultipleInternalArc也实现了Transition接口,代表转换后的状态,必须在postStates集合中。
private class MultipleInternalArc
implements Transition<OPERAND, STATE, EVENTTYPE, EVENT>{
// Fields
private Set<STATE> validPostStates;
private MultipleArcTransition<OPERAND, EVENT, STATE> hook; // transition hook
MultipleInternalArc(Set<STATE> postStates,
MultipleArcTransition<OPERAND, EVENT, STATE> hook) {
this.validPostStates = postStates;
this.hook = hook;
}
@Override
public STATE doTransition(OPERAND operand, STATE oldState,
EVENT event, EVENTTYPE eventType)
throws InvalidStateTransitonException {
STATE postState = hook.transition(operand, event);
if (!validPostStates.contains(postState)) {
throw new InvalidStateTransitonException(oldState, eventType);
}
return postState;
}
}
ApplicableSingleOrMultipleTransition的定义如下:
static private class ApplicableSingleOrMultipleTransition
<OPERAND, STATE extends Enum<STATE>,
EVENTTYPE extends Enum<EVENTTYPE>, EVENT>
implements ApplicableTransition<OPERAND, STATE, EVENTTYPE, EVENT> {
final STATE preState;
final EVENTTYPE eventType;
final Transition<OPERAND, STATE, EVENTTYPE, EVENT> transition;
ApplicableSingleOrMultipleTransition
(STATE preState, EVENTTYPE eventType,
Transition<OPERAND, STATE, EVENTTYPE, EVENT> transition) {
this.preState = preState;
this.eventType = eventType;
this.transition = transition;
}
@Override
public void apply
(StateMachineFactory<OPERAND, STATE, EVENTTYPE, EVENT> subject) {
Map<EVENTTYPE, Transition<OPERAND, STATE, EVENTTYPE, EVENT>> transitionMap
= subject.stateMachineTable.get(preState);
if (transitionMap == null) {
// I use HashMap here because I would expect most EVENTTYPE's to not
// apply out of a particular state, so FSM sizes would be
// quadratic if I use EnumMap's here as I do at the top level.
transitionMap = new HashMap<EVENTTYPE,
Transition<OPERAND, STATE, EVENTTYPE, EVENT>>();
subject.stateMachineTable.put(preState, transitionMap);
}
transitionMap.put(eventType, transition);
}
}
调用installTopolygy方法是可选的,当你使用factory没有同步时。
/**
* @return a StateMachineFactory just like {@code this}, except that if
* you won't need any synchronization to build a state machine
*
* Note that the returned StateMachineFactory is a distinct object.
*
* This method is part of the API.
*
* The only way you could distinguish the returned
* StateMachineFactory from {@code this} would be by
* measuring the performance of the derived
* {@code StateMachine} you can get from it.
*
* Calling this is optional. It doesn't change the semantics of the factory,
* if you call it then when you use the factory there is no synchronization.
*/
public StateMachineFactory
<OPERAND, STATE, EVENTTYPE, EVENT>
installTopology() {
return new StateMachineFactory<OPERAND, STATE, EVENTTYPE, EVENT>(this, true);
}
当StateMachineFactory建立之后,会调用stateMachine = stateMachineFactory.make(this); 来建立stateMachine。make的执行代码如下:
public StateMachine<STATE, EVENTTYPE, EVENT> make(OPERAND operand) {
return new InternalStateMachine(operand, defaultInitialState);
}
private class InternalStateMachine
implements StateMachine<STATE, EVENTTYPE, EVENT> {
private final OPERAND operand;
private STATE currentState;
InternalStateMachine(OPERAND operand, STATE initialState) {
this.operand = operand;
this.currentState = initialState;
if (!optimized) {
maybeMakeStateMachineTable();
}
}
@Override
public synchronized STATE getCurrentState() {
return currentState;
}
@Override
public synchronized STATE doTransition(EVENTTYPE eventType, EVENT event)
throws InvalidStateTransitonException {
currentState = StateMachineFactory.this.doTransition
(operand, currentState, eventType, event);
return currentState;
}
}
可以看到在构造方法⾥,判断是否进行过优化,如果没有,则调用maybemakeStateMachineTable,在 maybemakeStateMachineTable方法⾥,有一个优化,只当stateMachineTable为空时调用makeStateMachineTable.
private synchronized void maybeMakeStateMachineTable() {
if (stateMachineTable == null) {
makeStateMachineTable();
}
}
在makeStateMachineTable方法中,先把TransitionsListNode放到Stack中,然后逐个取出,调用apply(this)方法,实际调用的是ApplicableSingleOrMultipleTransition的apply(this)方法。
private void makeStateMachineTable() {
Stack<ApplicableTransition<OPERAND, STATE, EVENTTYPE, EVENT>> stack =
new Stack<ApplicableTransition<OPERAND, STATE, EVENTTYPE, EVENT>>();
Map<STATE, Map<EVENTTYPE, Transition<OPERAND, STATE, EVENTTYPE, EVENT>>>
prototype = new HashMap<STATE, Map<EVENTTYPE, Transition<OPERAND, STATE, EVENTTYPE, EVENT>>>();
prototype.put(defaultInitialState, null);
// I use EnumMap here because it'll be faster and denser. I would
// expect most of the states to have at least one transition.
stateMachineTable
= new EnumMap<STATE, Map<EVENTTYPE,
Transition<OPERAND, STATE, EVENTTYPE, EVENT>>>(prototype);
for (TransitionsListNode cursor = transitionsListNode;
cursor != null;
cursor = cursor.next) {
stack.push(cursor.transition);
}
while (!stack.isEmpty()) {
stack.pop().apply(this);
}
}
在ApplicableSingleOrMultipleTransition的apply()方法中,先用preState得到在preState状态下的变换表。这个表是根据事件类型和transition的一个映射。
@Override
public void apply
(StateMachineFactory<OPERAND, STATE, EVENTTYPE, EVENT> subject) {
Map<EVENTTYPE, Transition<OPERAND, STATE, EVENTTYPE, EVENT>> transitionMap
= subject.stateMachineTable.get(preState);
if (transitionMap == null) {
// I use HashMap here because I would expect most EVENTTYPE's to not
// apply out of a particular state, so FSM sizes would be
// quadratic if I use EnumMap's here as I do at the top level.
transitionMap = new HashMap<EVENTTYPE,
Transition<OPERAND, STATE, EVENTTYPE, EVENT>>();
subject.stateMachineTable.put(preState, transitionMap);
}
transitionMap.put(eventType, transition);
}
状态机的使用方法,首先用以下方法构建一个stateMachineFactory。。
protected static final
StateMachineFactory<JobStateMachine, JobStateInternal, JobEventType, JobEvent>
stateMachineFactory
= new StateMachineFactory<JobStateMachine, JobStateInternal, JobEventType, JobEvent>
(JobStateInternal.NEW)
.addTransition(JobStateInternal.NEW, JobStateInternal.INITED,
JobEventType.JOB_INIT,
new InitTransition())
.addTransition(JobStateInternal.INITED, JobStateInternal.SETUP,
JobEventType.JOB_START,
new StartTransition())
.addTransition(JobStateInternal.SETUP, JobStateInternal.RUNNING, JobEventType.JOB_SETUP_COMPLETED,new SetupCompletedTransition())
// .addTransition(JobStateInternal.RUNNING,EnumSet.of( JobStateInternal.KILLED,JobStateInternal.SUCCEEDED), JobEventType.JOB_COMPLETED,new JobTasksCompletedTransition())
.addTransition(JobStateInternal.RUNNING,JobStateInternal.SUCCEEDED, JobEventType.JOB_COMPLETED,new JobTasksCompletedTransition())
.installTopology();
每一个Transition都要实现SingleArcTransition.
public static class InitTransition
implements SingleArcTransition<JobStateMachine, JobEvent> {
@Override
public void transition(JobStateMachine job, JobEvent event) {
System.out.println("InitTransition Receiving event " + event);
job.eventHandler.handle(new JobEvent(job.getJobID(), JobEventType.JOB_START));
}
}
StateMachine一般有
@Override
public void handle(JobEvent event) {
try {
writeLock.lock();
JobStateInternal oldState = getInternalState();
try {
getStateMachine().doTransition(event.getType(), event);
} catch (InvalidStateTransitonException e) {
System.out.println("Can't handle this event at current state");
}
if (oldState != getInternalState()) {
System.out.println("Job Transitioned from " + oldState + " to "
+ getInternalState());
}
}
finally {
writeLock.unlock();
}
}
main方法如下:
public static void main(String[] args) throws IOException {
AsyncDispatcher dispatcher = new AsyncDispatcher();
//dispatcher.register(JobEventType.class, new JobEventDispatcher());
// dispatcher.register(TaskEventType.class, new TaskEventDispatcher());
YarnConfiguration conf = new YarnConfiguration(new Configuration());
dispatcher.init(conf);
dispatcher.start();
JobStateMachine jobStateMachine = new JobStateMachine("job001",dispatcher.getEventHandler());
dispatcher.register(JobEventType.class,jobStateMachine);
JobEvent jobEvent = new JobEvent("job002", JobEventType.JOB_INIT);
System.out.println("jobEvent:" + jobEvent.getType().getDeclaringClass());
dispatcher.getEventHandler().handle(new JobEvent("job002", JobEventType.JOB_INIT));
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dispatcher.stop();
dispatcher.close();
}