StateMachineFactory源代码详解

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();
  }







  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值