├── .gitignore ├── README.md └── src └── main └── java └── com └── jinku └── fsm ├── event ├── AbstractEvent.java ├── AsyncDispatcher.java ├── Dispatcher.java ├── EventHandler.java └── SyncDispatcher.java ├── example ├── GlobalStateManager.java ├── LocalStateEvent.java ├── LocalStateEventType.java └── LocalStateManager.java └── state ├── StateAutoSync.java ├── StateListener.java ├── StateManager.java └── StateTransition.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target/ 3 | *.iml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StateMachine 2 | 状态机通用实现 3 | https://juejin.im/post/5dfa241ce51d4558456bb44d 4 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/event/AbstractEvent.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.event; 2 | 3 | /** 4 | * 事件定义(包含事件枚举 和 事件数据) 5 | * 6 | * @param 7 | */ 8 | public abstract class AbstractEvent> { 9 | 10 | private final T type; 11 | 12 | public AbstractEvent(T type) { 13 | this.type = type; 14 | } 15 | 16 | public T getType() { 17 | return type; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "Event{" + "type=" + type + '}'; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/event/AsyncDispatcher.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.event; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | /** 9 | * 异步事件分发器,内部使用线程池来处理事件 10 | */ 11 | public class AsyncDispatcher implements Dispatcher { 12 | 13 | Map, EventHandler> eventHandlerMap; 14 | ExecutorService executor; 15 | 16 | public AsyncDispatcher() { 17 | eventHandlerMap = new ConcurrentHashMap<>(); 18 | this.executor = Executors.newSingleThreadExecutor(); 19 | } 20 | 21 | public AsyncDispatcher(int threadSize) { 22 | eventHandlerMap = new ConcurrentHashMap<>(); 23 | this.executor = Executors.newFixedThreadPool(threadSize); 24 | } 25 | 26 | public AsyncDispatcher(ExecutorService executor) { 27 | eventHandlerMap = new ConcurrentHashMap<>(); 28 | this.executor = executor; 29 | } 30 | 31 | @Override 32 | public void register(Class eventType, EventHandler handler) { 33 | eventHandlerMap.put(eventType, handler); 34 | } 35 | 36 | public void dispatch(final AbstractEvent event) { 37 | final EventHandler eventHandler = eventHandlerMap.get(event.getType().getClass()); 38 | if (eventHandler == null) { 39 | throw new RuntimeException("no matched event handler;type=" + event.getType()); 40 | } 41 | 42 | executor.execute(() -> { 43 | try { 44 | System.out.println("AsyncDispatcher handle event start;event=" + event); 45 | eventHandler.handle(event); 46 | System.out.println("AsyncDispatcher handle event end;event=" + event); 47 | } catch (Exception e) { 48 | System.out.println("AsyncDispatcher handle event exception;event=" + event); 49 | e.printStackTrace(); 50 | } 51 | }); 52 | } 53 | 54 | @Override 55 | public void shutdown() { 56 | executor.shutdown(); 57 | System.out.println("AsyncDispatcher shutdown"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/event/Dispatcher.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.event; 2 | 3 | /** 4 | * 事件分发器,负责维护事件与事件处理器和分发事件 5 | */ 6 | public interface Dispatcher { 7 | 8 | void register(Class eventType, EventHandler handler); 9 | 10 | void dispatch(final AbstractEvent event); 11 | 12 | void shutdown(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/event/EventHandler.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.event; 2 | 3 | /** 4 | * 事件处理器 5 | * 6 | * @param 7 | */ 8 | public interface EventHandler { 9 | 10 | /** 11 | * 处理T类型的事件 12 | * 13 | * @param event 14 | */ 15 | void handle(T event); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/event/SyncDispatcher.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.event; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | /** 7 | * 同步事件分发器 8 | */ 9 | public class SyncDispatcher implements Dispatcher { 10 | 11 | Map, EventHandler> eventHandlerMap; 12 | 13 | public SyncDispatcher() { 14 | eventHandlerMap = new ConcurrentHashMap<>(); 15 | } 16 | 17 | @Override 18 | public void register(Class eventType, EventHandler handler) { 19 | eventHandlerMap.put(eventType, handler); 20 | } 21 | 22 | public void dispatch(final AbstractEvent event) { 23 | final EventHandler eventHandler = eventHandlerMap.get(event.getType().getClass()); 24 | if (eventHandler == null) { 25 | throw new RuntimeException("no matched event handler;type=" + event.getType()); 26 | } 27 | 28 | try { 29 | System.out.println("SyncDispatcher handle event start;event=" + event); 30 | eventHandler.handle(event); 31 | System.out.println("SyncDispatcher handle event end;event=" + event); 32 | } catch (Exception e) { 33 | System.out.println("SyncDispatcher handle event exception;event=" + event); 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | @Override 39 | public void shutdown() { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/example/GlobalStateManager.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.example; 2 | 3 | import com.jinku.fsm.event.Dispatcher; 4 | import com.jinku.fsm.state.StateManager; 5 | 6 | /** 7 | * 全局状态管理器(比如数据库保存状态) 8 | * 实现逻辑 TODO(跟 本地状态管理器一致,不同之处在于 当前状态读取 和 状态更新) 9 | */ 10 | public abstract class GlobalStateManager extends StateManager { 11 | 12 | public GlobalStateManager(Dispatcher dispatcher) { 13 | super(dispatcher); 14 | } 15 | 16 | @Override 17 | public String managerKey() { 18 | return "global_state_manager"; 19 | } 20 | 21 | @Override 22 | public int currentState(String uuid) { 23 | // 从 数据库 读取 记录状态 24 | return 0; 25 | } 26 | 27 | @Override 28 | public boolean setState(String uuid, int newState, int expectState) { 29 | // 更改 数据库 对应记录的状态,使用乐观锁机制 30 | return false; 31 | } 32 | 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/example/LocalStateEvent.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.example; 2 | 3 | import com.jinku.fsm.event.AbstractEvent; 4 | 5 | public class LocalStateEvent extends AbstractEvent { 6 | 7 | private String uuid; 8 | 9 | public LocalStateEvent(String uuid, LocalStateEventType type) { 10 | super(type); 11 | this.uuid = uuid; 12 | } 13 | 14 | public String getUuid() { 15 | return uuid; 16 | } 17 | 18 | public void setUuid(String uuid) { 19 | this.uuid = uuid; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/example/LocalStateEventType.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.example; 2 | 3 | public enum LocalStateEventType { 4 | 5 | DoSomething(1, "do something"), 6 | Sync(2, "同步"), 7 | ; 8 | 9 | int type; 10 | String remark; 11 | 12 | LocalStateEventType(int type, String remark) { 13 | this.type = type; 14 | this.remark = remark; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/example/LocalStateManager.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.example; 2 | 3 | import com.jinku.fsm.event.AsyncDispatcher; 4 | import com.jinku.fsm.event.Dispatcher; 5 | import com.jinku.fsm.event.SyncDispatcher; 6 | import com.jinku.fsm.state.StateListener; 7 | import com.jinku.fsm.state.StateManager; 8 | import com.jinku.fsm.state.StateTransition; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * 本地状态管理器 15 | */ 16 | public class LocalStateManager extends StateManager { 17 | 18 | private volatile LocalStateEnum currentState = LocalStateEnum.Init; 19 | 20 | public LocalStateManager(Dispatcher dispatcher) { 21 | super(dispatcher); 22 | } 23 | 24 | @Override 25 | protected void init() { 26 | // 注册自动状态转移操作 27 | registerAutoTransition(new StateTransition() { 28 | @Override 29 | public List preState() { 30 | List list = new ArrayList<>(); 31 | list.add(LocalStateEnum.Processing.state); 32 | return list; 33 | } 34 | 35 | @Override 36 | public int operation(String uuid) { 37 | // do something than change state 38 | return LocalStateEnum.Success.getState(); 39 | } 40 | }); 41 | } 42 | 43 | @Override 44 | public String managerKey() { 45 | return "local_state_manager"; 46 | } 47 | 48 | @Override 49 | public int currentState(String uuid) { 50 | return currentState.getState(); 51 | } 52 | 53 | @Override 54 | public boolean setState(String uuid, int newState, int expectState) { 55 | 56 | if (expectState != currentState.state) { 57 | return false; 58 | } 59 | 60 | synchronized (this) { 61 | if (expectState != currentState.state) { 62 | return false; 63 | } 64 | currentState = LocalStateEnum.fromState(newState); 65 | } 66 | return true; 67 | } 68 | 69 | @Override 70 | public void handle(LocalStateEvent event) { 71 | // 处理同步事件 72 | if (event.getType() == LocalStateEventType.Sync) { 73 | autoSyncState(event.getUuid()); 74 | } 75 | 76 | if (event.getType() == LocalStateEventType.DoSomething) { 77 | doTransition(event.getUuid(), new StateTransition() { 78 | @Override 79 | public List preState() { 80 | List list = new ArrayList<>(); 81 | list.add(LocalStateEnum.Init.state); 82 | return list; 83 | } 84 | 85 | @Override 86 | public int operation(String uuid) { 87 | // do something than change state 88 | return LocalStateEnum.Processing.state; 89 | } 90 | }); 91 | } 92 | } 93 | 94 | public enum LocalStateEnum { 95 | 96 | Init(0, "初始化"), 97 | Processing(1, "处理中"), 98 | Success(2, "成功"), 99 | Failed(3, "失败"), 100 | ; 101 | 102 | int state; 103 | String remark; 104 | 105 | LocalStateEnum(int state, String remark) { 106 | this.state = state; 107 | this.remark = remark; 108 | } 109 | 110 | public static LocalStateEnum fromState(Integer state) { 111 | if (state == null) { 112 | return null; 113 | } 114 | for (LocalStateEnum stateEnum : LocalStateEnum.values()) { 115 | if (stateEnum.state == state) { 116 | return stateEnum; 117 | } 118 | } 119 | return null; 120 | } 121 | 122 | public int getState() { 123 | return state; 124 | } 125 | 126 | public String getRemark() { 127 | return remark; 128 | } 129 | } 130 | 131 | /** 132 | * 本地状态管理器 调用示例 133 | * 134 | * @param args 135 | */ 136 | public static void main(String[] args) { 137 | // Dispatcher dispatcher = new SyncDispatcher(); 138 | Dispatcher dispatcher = new AsyncDispatcher(); 139 | StateManager localStateManager = new LocalStateManager(dispatcher); 140 | /** 141 | * 注册状态变化监听器 142 | */ 143 | localStateManager.registerListener(new StateListener() { 144 | @Override 145 | public void stateChanged(String uuid, int preState, int postState) { 146 | // do something 147 | } 148 | }); 149 | 150 | dispatcher.register(LocalStateEventType.class, localStateManager); 151 | 152 | String uuid = "1223333"; 153 | // 分发事件do something 154 | LocalStateEvent localStateEvent = new LocalStateEvent(uuid, LocalStateEventType.DoSomething); 155 | dispatcher.dispatch(localStateEvent); 156 | 157 | // 分发事件同步数据 158 | localStateEvent = new LocalStateEvent(uuid, LocalStateEventType.Sync); 159 | dispatcher.dispatch(localStateEvent); 160 | 161 | // 程序退出要关闭分发器 162 | dispatcher.shutdown(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/state/StateAutoSync.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.state; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 状态自动同步 8 | */ 9 | public class StateAutoSync { 10 | 11 | List managerList = new ArrayList<>(); 12 | 13 | /** 14 | * 注册状态管理器 15 | * 16 | * @param stateManager 17 | */ 18 | public synchronized void register(StateManager stateManager) { 19 | if (managerList.contains(stateManager)) { 20 | return; 21 | } 22 | managerList.add(stateManager); 23 | } 24 | 25 | public void syncState(String uuid, String managerKey) { 26 | List innerManagerList= new ArrayList<>(managerList); 27 | StateManager matchedStateManager = null; 28 | for (StateManager stateManager : innerManagerList) { 29 | if (stateManager.managerKey().equalsIgnoreCase(managerKey)) { 30 | matchedStateManager = stateManager; 31 | } 32 | } 33 | innerManagerList.clear(); 34 | if (matchedStateManager == null) { 35 | return; 36 | } 37 | 38 | matchedStateManager.autoSyncState(uuid); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/state/StateListener.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.state; 2 | 3 | public interface StateListener { 4 | 5 | /** 6 | * preState --> postState 状态变化时触发的操作 7 | */ 8 | void stateChanged(String uuid, int preState, int postState); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/state/StateManager.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.state; 2 | 3 | import com.jinku.fsm.event.AbstractEvent; 4 | import com.jinku.fsm.event.Dispatcher; 5 | import com.jinku.fsm.event.EventHandler; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public abstract class StateManager implements EventHandler { 11 | 12 | private List listeners = new ArrayList<>(); 13 | private List autoTransitions = new ArrayList<>(); 14 | 15 | protected Dispatcher dispatcher; 16 | 17 | public StateManager(Dispatcher dispatcher) { 18 | this.dispatcher = dispatcher; 19 | init(); 20 | } 21 | 22 | /** 23 | * 初始话方法,子类实现 24 | */ 25 | protected abstract void init(); 26 | 27 | /** 28 | * 状态管理器标识 29 | * 30 | * @return 31 | */ 32 | public abstract String managerKey(); 33 | 34 | /** 35 | * 当前状态 36 | * 37 | * @return 38 | */ 39 | protected abstract int currentState(String uuid); 40 | 41 | /** 42 | * 更新状态 43 | * 44 | * @param uuid 45 | * @param newState 46 | * @param expectState 47 | */ 48 | protected abstract boolean setState(String uuid, int newState, int expectState); 49 | 50 | /** 51 | * 注册状态监听器 52 | * 53 | * @param listener 54 | */ 55 | public synchronized void registerListener(StateListener listener) { 56 | if (listeners.contains(listener)) { 57 | return; 58 | } 59 | listeners.add(listener); 60 | } 61 | 62 | /** 63 | * 注册自动状态转换动作 64 | * 65 | * @param transition 66 | */ 67 | protected void registerAutoTransition(StateTransition transition) { 68 | if (autoTransitions.contains(transition)) { 69 | return; 70 | } 71 | autoTransitions.add(transition); 72 | } 73 | 74 | /** 75 | * 执行状态转换操作 76 | * 77 | * @param uuid 78 | * @param transition 79 | */ 80 | protected void doTransition(String uuid, StateTransition transition) { 81 | int current = currentState(uuid); 82 | if (!transition.preState().contains(current)) { 83 | return; 84 | } 85 | 86 | System.out.println(managerKey() + " manual do: currentState=" + current); 87 | System.out.println(managerKey() + " manual do: do something"); 88 | int newState = transition.operation(uuid); 89 | System.out.println(managerKey() + " manual do: newState=" + newState); 90 | boolean isSuccess = setState(uuid, newState, current); 91 | System.out.println(managerKey() + " manual do: setState result=" + isSuccess); 92 | if (isSuccess) { 93 | notifyListeners(uuid, current, newState); 94 | } 95 | } 96 | 97 | /** 98 | * 自动同步状态 99 | * 100 | * @param uuid 101 | */ 102 | public void autoSyncState(String uuid) { 103 | List innerAutoTransitions = new ArrayList<>(autoTransitions); 104 | if (innerAutoTransitions.size() == 0) { 105 | return; 106 | } 107 | 108 | int current = currentState(uuid); 109 | while (true) { 110 | StateTransition matchedTransition = null; 111 | for (StateTransition transition : innerAutoTransitions) { 112 | if (transition.preState().contains(current)) { 113 | matchedTransition = transition; 114 | } 115 | } 116 | if (matchedTransition == null) { 117 | break; 118 | } 119 | System.out.println(managerKey() + " autoSync: currentState=" + current); 120 | System.out.println(managerKey() + " autoSync: do something"); 121 | int newState = matchedTransition.operation(uuid); 122 | System.out.println(managerKey() + " autoSync: newState=" + newState); 123 | boolean isSuccess = setState(uuid, newState, current); 124 | System.out.println(managerKey() + " autoSync: setState result=" + isSuccess); 125 | 126 | notifyListeners(uuid, current, newState); 127 | 128 | if (isSuccess) { 129 | current = newState; 130 | } else { 131 | current = currentState(uuid); 132 | } 133 | } 134 | } 135 | 136 | private void notifyListeners(String uuid, int current, int newState) { 137 | try { 138 | // 通知 139 | List innerListeners = new ArrayList<>(listeners); 140 | for (StateListener listener : innerListeners) { 141 | System.out.println(managerKey() + " notify listener; uuid=" + uuid + ";oldState=" + current + ";newState=" + newState); 142 | listener.stateChanged(uuid, current, newState); 143 | } 144 | } catch (Exception e) { 145 | System.err.print(managerKey() + " notify listener exception"); 146 | e.printStackTrace(); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/com/jinku/fsm/state/StateTransition.java: -------------------------------------------------------------------------------- 1 | package com.jinku.fsm.state; 2 | 3 | import java.util.List; 4 | 5 | public interface StateTransition { 6 | 7 | /** 8 | * 前置状态 9 | * 10 | * @return 11 | */ 12 | List preState(); 13 | 14 | /** 15 | * 执行的操作,返回操作后的状态 16 | */ 17 | int operation(String uuid); 18 | } 19 | --------------------------------------------------------------------------------