General implementation of state machine

Keywords: Java

Related concepts

  • FSM (finite state machine): a state machine with a finite number of States, which is the most commonly used state machine and the object of general discussion
  • Infinite State Machine: a state machine with an infinite number of States, rarely used
  • State: a state that can be reached by a state
  • State transition: the transition of a state machine from one state to another
  • Input / input / event / event: an event input that can be received and processed by the state machine, which may cause state changes

The UML representation of the general state is as follows:

General implementation of state machine

A player example

public enum State {

    IDLE,

    DATA_SOURCE,

    PREPARING,

    PREPARED,

    STARTING,

    STARTED,

    BUFFERING,

    READY,

    SWITCHING_PROGRAM,

    SWITCHING_CHANNEL,

    SWITCHING_DEFINITION,

    SWITCHING_ENGINE,

    STOPPING,

    RELEASING,

    ERROR
}

The order of States is very important. Try to follow the form of stack, and deal with special states, such as error.

public class Event {

    public static class SetDataSourceEvent extends LoopEvent {
        public Uri uri;

        public SetDataSourceEvent() {}

        public SetDataSourceEvent(Uri uri) {
            this.uri = uri;
        }
    }

    public static class PrepareEvent extends LoopEvent {}

    public static class StartEvent extends LoopEvent {}

    public static class SwitchChannelEvent extends LoopEvent {
        public int cateIndex;
        public int channelIndex;

        public SwitchChannelEvent() {}

        public SwitchChannelEvent(int cateIndex, int channelIndex) {
            this.cateIndex = cateIndex;
            this.channelIndex = channelIndex;
        }
    }

    public static class SwitchDefinitionEvent extends LoopEvent {
        public int definition;

        public SwitchDefinitionEvent() {}

        public SwitchDefinitionEvent(int definition) {
            this.definition = definition;
        }
    }

    public static class SwitchEngineEvent extends LoopEvent {
        public String engine;

        public SwitchEngineEvent() {}

        public SwitchEngineEvent(String engine) {
            this.engine = engine;
        }
    }

    public static class StopEvent extends LoopEvent {}
}
public abstract class Action {
    protected abstract void doAction() throws Exception;
}

public class Action1 extends Action {
    protected void doAction() throws Exception {
        // xxxx
        // update state
    }
}

...
public abstract class LoopStateMachine {

    private ActionThread mActionThread = new ActionThread("LoopActionThread");

    private BlockingQueue<Action> mActionQueue = new ArrayBlockingQueue<>(100);

    private State mState;

    public void sendEvent(Event event) {
        // Create an action based on the event and insert it into the mpactionqueue
    }

    private class ActionThread extends Thread {
        public ActionThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            super.run();
            while (true) {
                try {
                    LoopAction action = mActionQueue.take();
                    action.doAction();
                } catch (Exception e) {
                    Logger.w(TAG, "$ActionThread#run(): exception", e);

                    mState = State.ERROR;
                    // Continue
                }
            }
        }
    }
}

Posted by sandrol76 on Tue, 26 Nov 2019 11:49:46 -0800