From d5073ae245457fed804e8ee9658aa19b8699f165 Mon Sep 17 00:00:00 2001 From: SerLiunx-ctrl <17689543@qq.com> Date: Tue, 31 Dec 2024 11:20:22 +0800 Subject: [PATCH] =?UTF-8?q?change:=20=E8=B0=83=E6=95=B4=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=9C=BA=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../machine/AbstractStateMachine.java | 251 ++++++++++++++++++ .../machine/StandardStateMachine.java | 211 +-------------- .../statemanagement/machine/StateMachine.java | 13 +- .../machine/StateMachineBuilder.java | 73 +++-- .../machine/StateMachineType.java | 18 ++ .../serliunx/statemanagement/MachineTest.java | 26 +- 6 files changed, 358 insertions(+), 234 deletions(-) create mode 100644 src/main/java/com/serliunx/statemanagement/machine/AbstractStateMachine.java create mode 100644 src/main/java/com/serliunx/statemanagement/machine/StateMachineType.java diff --git a/src/main/java/com/serliunx/statemanagement/machine/AbstractStateMachine.java b/src/main/java/com/serliunx/statemanagement/machine/AbstractStateMachine.java new file mode 100644 index 0000000..aea3c1b --- /dev/null +++ b/src/main/java/com/serliunx/statemanagement/machine/AbstractStateMachine.java @@ -0,0 +1,251 @@ +package com.serliunx.statemanagement.machine; + +import com.serliunx.statemanagement.machine.handler.StateHandler; +import com.serliunx.statemanagement.machine.handler.StateHandlerProcessParams; +import com.serliunx.statemanagement.machine.handler.StateHandlerWrapper; +import com.serliunx.statemanagement.manager.AbstractStateManager; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; + +/** + * 状态机抽象实现, 实现最基本功能 + * + * @author SerLiunx + * @version 1.0.0 + * @since 2024/12/31 + */ +public abstract class AbstractStateMachine extends AbstractStateManager implements StateMachine { + + /** + * 进入事件集合 + */ + protected final Map>> entryHandlers; + /** + * 离开事件集合 + */ + protected final Map>> leaveHandlers; + /** + * 交换事件集合 + */ + protected final Map>> exchangeHandlers; + /** + * 异步执行器 + */ + protected final Executor executor; + /** + * 是否异步执行 + *

+ * 当具体的执行器没有指定是否异步时, 将根据该值决定是否异步执行. + */ + protected final Boolean async; + + /** + * 默认的构造函数 + * + * @param entryHandlers 进入事件处理器集合 + * @param leaveHandlers 离开事件处理器集合 + * @param exchangeHandlers 交换事件处理器集合 + * @param executor 异步执行器 + * @param async 是否异步执行 + */ + AbstractStateMachine(List stateList, + Map>> entryHandlers, + Map>> leaveHandlers, + Map>> exchangeHandlers, + Executor executor, + Boolean async + ) { + super(stateList); + this.entryHandlers = entryHandlers; + this.leaveHandlers = leaveHandlers; + this.exchangeHandlers = exchangeHandlers; + this.executor = executor; + this.async = async; + } + + @Override + public void close() throws Exception { + if (executor == null) { + return; + } + if (executor instanceof ExecutorService) { + ExecutorService es = (ExecutorService) executor; + es.shutdown(); + } else if (executor instanceof AutoCloseable) { + AutoCloseable ac = (AutoCloseable) executor; + ac.close(); + } + } + + @Override + public S switchPrevAndGet() { + try { + writeLock.lock(); + S oldState = get(); + prev(); + S newState = get(); + invokeHandlers(oldState, newState); + return newState; + } finally { + writeLock.unlock(); + } + } + + @Override + public S getAndSwitchPrev() { + try { + writeLock.lock(); + S oldState = get(); + prev(); + S newState = get(); + invokeHandlers(oldState, newState); + return oldState; + } finally { + writeLock.unlock(); + } + } + + @Override + public void switchPrev() { + try { + writeLock.lock(); + S oldState = get(); + prev(); + S newState = get(); + invokeHandlers(oldState, newState); + } finally { + writeLock.unlock(); + } + } + + @Override + public S switchNextAndGet() { + try { + writeLock.lock(); + S oldState = get(); + next(); + S newState = get(); + invokeHandlers(oldState, newState); + return newState; + } finally { + writeLock.unlock(); + } + } + + @Override + public S getAndSwitchNext() { + try { + writeLock.lock(); + S oldState = get(); + next(); + S newState = get(); + invokeHandlers(oldState, newState); + return oldState; + } finally { + writeLock.unlock(); + } + } + + @Override + public void switchNext() { + try { + writeLock.lock(); + S oldState = get(); + next(); + S newState = get(); + invokeHandlers(oldState, newState); + } finally { + writeLock.unlock(); + } + } + + @Override + public boolean switchTo(S state) { + int i = indexOf(state); + if (i == -1 || i == currentIndex()) { + return false; + } + try { + writeLock.lock(); + // 重新检查 + if (i == currentIndex()) { + return false; + } + S oldState = get(); + boolean result = super.switchTo(state); + if (result) { + S newState = get(); + invokeHandlers(oldState, newState); + } + return result; + } finally { + writeLock.unlock(); + } + } + + @Override + public void reset() { + try { + writeLock.lock(); + S oldState = get(); + super.reset(); + S newState = get(); + invokeHandlers(oldState, newState); + } finally { + writeLock.unlock(); + } + } + + /** + * 触发处理器 + * + * @param from 源状态 + * @param to 目的状态 + */ + protected final void invokeHandlers(S from, S to) { + // 触发离开处理器 + doInvokeHandlers(leaveHandlers.get(from), from, to); + + // 触发进入处理器 + doInvokeHandlers(entryHandlers.get(to), from, to); + + // 触发交换处理器 + final String key = from.toString() + "-" + to.toString(); + doInvokeHandlers(exchangeHandlers.get(key), from, to); + } + + /** + * 触发 + */ + private void doInvokeHandlers(List> handlerWrappers, S from, S to) { + if (handlerWrappers == null) { + return; + } + // 全局的异步状态 + final boolean isGlobalAsync = async != null && async; + + handlerWrappers.forEach(hw -> { + final StateHandler stateHandler; + if (hw == null || + (stateHandler = hw.getStateHandler()) == null) { + return; + } + + final Executor executorToRun = hw.getExecutor() == null ? executor : hw.getExecutor(); + final boolean runInAsync = hw.getAsync() == null ? isGlobalAsync : hw.getAsync(); + final StateHandlerProcessParams params = new StateHandlerProcessParams<>(from, to, null); + + if (runInAsync) { + if (executorToRun == null) { + throw new NullPointerException(); + } + executorToRun.execute(() -> stateHandler.handle(params)); + } else { + stateHandler.handle(params); + } + }); + } +} diff --git a/src/main/java/com/serliunx/statemanagement/machine/StandardStateMachine.java b/src/main/java/com/serliunx/statemanagement/machine/StandardStateMachine.java index 3972c1c..8d1c7d4 100644 --- a/src/main/java/com/serliunx/statemanagement/machine/StandardStateMachine.java +++ b/src/main/java/com/serliunx/statemanagement/machine/StandardStateMachine.java @@ -1,9 +1,6 @@ package com.serliunx.statemanagement.machine; -import com.serliunx.statemanagement.machine.handler.StateHandler; -import com.serliunx.statemanagement.machine.handler.StateHandlerProcessParams; import com.serliunx.statemanagement.machine.handler.StateHandlerWrapper; -import com.serliunx.statemanagement.manager.AbstractStateManager; import java.util.List; import java.util.Map; @@ -16,39 +13,16 @@ import java.util.concurrent.Executor; * @version 1.0.0 * @since 2024/12/28 */ -public class StandardStateMachine extends AbstractStateManager implements StateMachine { - - /** - * 进入事件集合 - */ - private final Map>> entryHandlers; - /** - * 离开事件集合 - */ - private final Map>> leaveHandlers; - /** - * 交换事件集合 - */ - private final Map>> exchangeHandlers; - /** - * 异步执行器 - */ - private final Executor executor; - /** - * 是否异步执行 - *

- * 当具体的执行器没有指定是否异步时, 将根据该值决定是否异步执行. - */ - private final Boolean async; +public class StandardStateMachine extends AbstractStateMachine implements StateMachine { /** * 默认的构造函数 * - * @param entryHandlers 进入事件处理器集合 - * @param leaveHandlers 离开事件处理器集合 - * @param exchangeHandlers 交换事件处理器集合 - * @param executor 异步执行器 - * @param async 是否异步执行 + * @param entryHandlers 进入事件处理器集合 + * @param leaveHandlers 离开事件处理器集合 + * @param exchangeHandlers 交换事件处理器集合 + * @param executor 异步执行器 + * @param async 是否异步执行 */ StandardStateMachine(List stateList, Map>> entryHandlers, @@ -57,180 +31,11 @@ public class StandardStateMachine extends AbstractStateManager implements Executor executor, Boolean async ) { - super(stateList); - this.entryHandlers = entryHandlers; - this.leaveHandlers = leaveHandlers; - this.exchangeHandlers = exchangeHandlers; - this.executor = executor; - this.async = async; + super(stateList, entryHandlers, leaveHandlers, exchangeHandlers, executor, async); } @Override - public S switchPrevAndGet() { - try { - writeLock.lock(); - S oldState = get(); - prev(); - S newState = get(); - invokeHandlers(oldState, newState); - return newState; - } finally { - writeLock.unlock(); - } - } + public void publish(Object event) { - @Override - public S getAndSwitchPrev() { - try { - writeLock.lock(); - S oldState = get(); - prev(); - S newState = get(); - invokeHandlers(oldState, newState); - return oldState; - } finally { - writeLock.unlock(); - } - } - - @Override - public void switchPrev() { - try { - writeLock.lock(); - S oldState = get(); - prev(); - S newState = get(); - invokeHandlers(oldState, newState); - } finally { - writeLock.unlock(); - } - } - - @Override - public S switchNextAndGet() { - try { - writeLock.lock(); - S oldState = get(); - next(); - S newState = get(); - invokeHandlers(oldState, newState); - return newState; - } finally { - writeLock.unlock(); - } - } - - @Override - public S getAndSwitchNext() { - try { - writeLock.lock(); - S oldState = get(); - next(); - S newState = get(); - invokeHandlers(oldState, newState); - return oldState; - } finally { - writeLock.unlock(); - } - } - - @Override - public void switchNext() { - try { - writeLock.lock(); - S oldState = get(); - next(); - S newState = get(); - invokeHandlers(oldState, newState); - } finally { - writeLock.unlock(); - } - } - - @Override - public boolean switchTo(S state) { - int i = indexOf(state); - if (i == -1 || i == currentIndex()) { - return false; - } - try { - writeLock.lock(); - // 重新检查 - if (i == currentIndex()) { - return false; - } - S oldState = get(); - boolean result = super.switchTo(state); - if (result) { - S newState = get(); - invokeHandlers(oldState, newState); - } - return result; - } finally { - writeLock.unlock(); - } - } - - @Override - public void reset() { - try { - writeLock.lock(); - S oldState = get(); - super.reset(); - S newState = get(); - invokeHandlers(oldState, newState); - } finally { - writeLock.unlock(); - } - } - - /** - * 触发处理器 - * - * @param from 源状态 - * @param to 目的状态 - */ - private void invokeHandlers(S from, S to) { - // 触发离开处理器 - doInvokeHandlers(leaveHandlers.get(from), from, to); - - // 触发进入处理器 - doInvokeHandlers(entryHandlers.get(to), from, to); - - // 触发交换处理器 - final String key = from.toString() + "-" + to.toString(); - doInvokeHandlers(exchangeHandlers.get(key), from, to); - } - - /** - * 触发 - */ - private void doInvokeHandlers(List> handlerWrappers, S from, S to) { - if (handlerWrappers == null) { - return; - } - // 全局的异步状态 - final boolean isGlobalAsync = async != null && async; - - handlerWrappers.forEach(hw -> { - final StateHandler stateHandler; - if (hw == null || - (stateHandler = hw.getStateHandler()) == null) { - return; - } - - final Executor executorToRun = hw.getExecutor() == null ? executor : hw.getExecutor(); - final boolean runInAsync = hw.getAsync() == null ? isGlobalAsync : hw.getAsync(); - final StateHandlerProcessParams params = new StateHandlerProcessParams<>(from, to, null); - - if (runInAsync) { - if (executorToRun == null) { - throw new NullPointerException(); - } - executorToRun.execute(() -> stateHandler.handle(params)); - } else { - stateHandler.handle(params); - } - }); } } diff --git a/src/main/java/com/serliunx/statemanagement/machine/StateMachine.java b/src/main/java/com/serliunx/statemanagement/machine/StateMachine.java index 16f09d8..9abe350 100644 --- a/src/main/java/com/serliunx/statemanagement/machine/StateMachine.java +++ b/src/main/java/com/serliunx/statemanagement/machine/StateMachine.java @@ -11,7 +11,7 @@ import com.serliunx.statemanagement.manager.BidirectionalStateManager; *

  • 切出指定状态时触发 (离开事件) *
  • 从A切换到B状态时触发 (交换事件) *

    - * 请使用{@link StateMachineBuilder} 来构建状态机. + * 请使用 {@link StateMachineBuilder} 来构建状态机. * * @author SerLiunx * @version 1.0.0 @@ -20,10 +20,17 @@ import com.serliunx.statemanagement.manager.BidirectionalStateManager; * @see BidirectionalStateManager * @see com.serliunx.statemanagement.manager.StateManager */ -public interface StateMachine extends BidirectionalStateManager { +public interface StateMachine extends BidirectionalStateManager, AutoCloseable { /** - * 切换到指定状态 + * 发布事件 + * + * @param event 事件 + */ + void publish(Object event); + + /** + * 切换至指定状态 *

  • 在使用状态机的情况, 仅切换成功才会触发注册的各种事件. * * @param state 新的状态 diff --git a/src/main/java/com/serliunx/statemanagement/machine/StateMachineBuilder.java b/src/main/java/com/serliunx/statemanagement/machine/StateMachineBuilder.java index a5bf711..420a33f 100644 --- a/src/main/java/com/serliunx/statemanagement/machine/StateMachineBuilder.java +++ b/src/main/java/com/serliunx/statemanagement/machine/StateMachineBuilder.java @@ -18,7 +18,7 @@ public final class StateMachineBuilder { /** * 状态管理器 */ - private List stateList; + private final List stateList; /** * 执行器 */ @@ -27,6 +27,10 @@ public final class StateMachineBuilder { * 是否异步执行 */ private Boolean async; + /** + * 状态机类型 + */ + private StateMachineType type = StateMachineType.STANDARD; /** * 各种事件 @@ -35,8 +39,14 @@ public final class StateMachineBuilder { private final Map>> leaveHandlers = new HashMap<>(64); private final Map>> exchangeHandlers = new HashMap<>(64); - // private-ctor - private StateMachineBuilder() {} + private StateMachineBuilder(List states) { + this.stateList = states; + } + + private StateMachineBuilder(S[] states) { + this(Arrays.asList(states)); + } + /** * 添加交换事件 @@ -189,18 +199,33 @@ public final class StateMachineBuilder { } /** - * 设置状态列表 + * 指定状态机的类型 + *
  • 状态机并发与否并不影响事件的执行逻辑 + * + * @param type 类型 */ - public StateMachineBuilder states(S[] states) { - return states(Arrays.asList(states)); + public StateMachineBuilder type(StateMachineType type) { + if (type == null) { + throw new NullPointerException(); + } + this.type = type; + return this; } /** - * 设置状态列表 + * 指定状态机的类型为标准型 + *
  • 状态机并发与否并不影响事件的执行逻辑 */ - public StateMachineBuilder states(List states) { - stateList = states; - return this; + public StateMachineBuilder standard() { + return type(StateMachineType.STANDARD); + } + + /** + * 指定状态机的类型为并发型 + *
  • 状态机并发与否并不影响事件的执行逻辑 + */ + public StateMachineBuilder concurrent() { + return type(StateMachineType.CONCURRENT); } /** @@ -208,19 +233,33 @@ public final class StateMachineBuilder { */ @SuppressWarnings("unchecked") public > M build() { - return (M) new StandardStateMachine<>(stateList, entryHandlers, - leaveHandlers, exchangeHandlers, executor, async); + if (type == null) { + throw new NullPointerException(); + } + if (type.equals(StateMachineType.STANDARD)) { + return (M)new StandardStateMachine<>(stateList, entryHandlers, + leaveHandlers, exchangeHandlers, executor, async); + } + throw new IllegalArgumentException("未知的状态机类型: " + type); } /** * 状态机构建器 * - * @param stateClass 状态类 + * @param states 状态集合 * @return 状态机构建器实例 - * @param 状态类参数 */ - @SuppressWarnings("all") - public static StateMachineBuilder from(Class stateClass) { - return new StateMachineBuilder<>(); + public static StateMachineBuilder from(S[] states) { + return new StateMachineBuilder<>(states); + } + + /** + * 状态机构建器 + * + * @param states 状态集合 + * @return 状态机构建器实例 + */ + public static StateMachineBuilder from(List states) { + return new StateMachineBuilder<>(states); } } diff --git a/src/main/java/com/serliunx/statemanagement/machine/StateMachineType.java b/src/main/java/com/serliunx/statemanagement/machine/StateMachineType.java new file mode 100644 index 0000000..e33145e --- /dev/null +++ b/src/main/java/com/serliunx/statemanagement/machine/StateMachineType.java @@ -0,0 +1,18 @@ +package com.serliunx.statemanagement.machine; + +/** + * 状态机类型 + * + * @author SerLiunx + * @since 2024/12/31 + */ +public enum StateMachineType { + /** + * 标准, 切换使用读写锁 + */ + STANDARD, + /** + * 并发型, 切换使用CAS乐观锁 + */ + CONCURRENT; +} diff --git a/src/test/java/com/serliunx/statemanagement/MachineTest.java b/src/test/java/com/serliunx/statemanagement/MachineTest.java index 7f15600..ae4186b 100644 --- a/src/test/java/com/serliunx/statemanagement/MachineTest.java +++ b/src/test/java/com/serliunx/statemanagement/MachineTest.java @@ -19,26 +19,30 @@ import java.util.concurrent.Executors; public class MachineTest { @Test - public void testStandardStateMachine() { - StateMachine stateMachine = StateMachineBuilder.from(PrinterState.class) - .async(false) - .states(PrinterState.values()) + public void testStandardStateMachine() throws Exception { + StateMachine stateMachine = StateMachineBuilder.from(PrinterState.values()) + .async() + .standard() .executor(Executors.newFixedThreadPool(16)) .whenLeave(PrinterState.PRINTING, h -> { System.out.println(Thread.currentThread().getName() + ": leave PRINTING"); }) - .whenEntry(PrinterState.SCANNING, h -> { - System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo()); + .whenEntry(PrinterState.STOPPING, h -> { + System.out.println(Thread.currentThread().getName() + ": entry STOPPING, from " + h.getFrom()); }) - .whenEntry(PrinterState.PRINTING, h -> { - System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo()); - }) - .exchange(PrinterState.STOPPED, PrinterState.IDLE, h -> { - System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo()); + .whenEntry(PrinterState.STOPPED, h -> { + System.out.println(Thread.currentThread().getName() + ": entry STOPPED, from " + h.getFrom()); }) .build(); + System.out.println(stateMachine.getClass()); + stateMachine.switchTo(PrinterState.PRINTING); stateMachine.switchNext(); + stateMachine.switchNext(); + + System.out.println(stateMachine.current()); + + stateMachine.close(); } }