change: 调整状态机代码结构.

This commit is contained in:
2024-12-31 11:20:22 +08:00
parent 5fed1bbf19
commit d5073ae245
6 changed files with 358 additions and 234 deletions

View File

@@ -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 <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/31
*/
public abstract class AbstractStateMachine<S> extends AbstractStateManager<S> implements StateMachine<S> {
/**
* 进入事件集合
*/
protected final Map<S, List<StateHandlerWrapper<S>>> entryHandlers;
/**
* 离开事件集合
*/
protected final Map<S, List<StateHandlerWrapper<S>>> leaveHandlers;
/**
* 交换事件集合
*/
protected final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers;
/**
* 异步执行器
*/
protected final Executor executor;
/**
* 是否异步执行
* <p>
* 当具体的执行器没有指定是否异步时, 将根据该值决定是否异步执行.
*/
protected final Boolean async;
/**
* 默认的构造函数
*
* @param entryHandlers 进入事件处理器集合
* @param leaveHandlers 离开事件处理器集合
* @param exchangeHandlers 交换事件处理器集合
* @param executor 异步执行器
* @param async 是否异步执行
*/
AbstractStateMachine(List<S> stateList,
Map<S, List<StateHandlerWrapper<S>>> entryHandlers,
Map<S, List<StateHandlerWrapper<S>>> leaveHandlers,
Map<String, List<StateHandlerWrapper<S>>> 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<StateHandlerWrapper<S>> handlerWrappers, S from, S to) {
if (handlerWrappers == null) {
return;
}
// 全局的异步状态
final boolean isGlobalAsync = async != null && async;
handlerWrappers.forEach(hw -> {
final StateHandler<S> 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<S> params = new StateHandlerProcessParams<>(from, to, null);
if (runInAsync) {
if (executorToRun == null) {
throw new NullPointerException();
}
executorToRun.execute(() -> stateHandler.handle(params));
} else {
stateHandler.handle(params);
}
});
}
}

View File

@@ -1,9 +1,6 @@
package com.serliunx.statemanagement.machine; 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.machine.handler.StateHandlerWrapper;
import com.serliunx.statemanagement.manager.AbstractStateManager;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -16,39 +13,16 @@ import java.util.concurrent.Executor;
* @version 1.0.0 * @version 1.0.0
* @since 2024/12/28 * @since 2024/12/28
*/ */
public class StandardStateMachine<S> extends AbstractStateManager<S> implements StateMachine<S> { public class StandardStateMachine<S> extends AbstractStateMachine<S> implements StateMachine<S> {
/**
* 进入事件集合
*/
private final Map<S, List<StateHandlerWrapper<S>>> entryHandlers;
/**
* 离开事件集合
*/
private final Map<S, List<StateHandlerWrapper<S>>> leaveHandlers;
/**
* 交换事件集合
*/
private final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers;
/**
* 异步执行器
*/
private final Executor executor;
/**
* 是否异步执行
* <p>
* 当具体的执行器没有指定是否异步时, 将根据该值决定是否异步执行.
*/
private final Boolean async;
/** /**
* 默认的构造函数 * 默认的构造函数
* *
* @param entryHandlers 进入事件处理器集合 * @param entryHandlers 进入事件处理器集合
* @param leaveHandlers 离开事件处理器集合 * @param leaveHandlers 离开事件处理器集合
* @param exchangeHandlers 交换事件处理器集合 * @param exchangeHandlers 交换事件处理器集合
* @param executor 异步执行器 * @param executor 异步执行器
* @param async 是否异步执行 * @param async 是否异步执行
*/ */
StandardStateMachine(List<S> stateList, StandardStateMachine(List<S> stateList,
Map<S, List<StateHandlerWrapper<S>>> entryHandlers, Map<S, List<StateHandlerWrapper<S>>> entryHandlers,
@@ -57,180 +31,11 @@ public class StandardStateMachine<S> extends AbstractStateManager<S> implements
Executor executor, Executor executor,
Boolean async Boolean async
) { ) {
super(stateList); super(stateList, entryHandlers, leaveHandlers, exchangeHandlers, executor, async);
this.entryHandlers = entryHandlers;
this.leaveHandlers = leaveHandlers;
this.exchangeHandlers = exchangeHandlers;
this.executor = executor;
this.async = async;
} }
@Override @Override
public S switchPrevAndGet() { public void publish(Object event) {
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 目的状态
*/
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<StateHandlerWrapper<S>> handlerWrappers, S from, S to) {
if (handlerWrappers == null) {
return;
}
// 全局的异步状态
final boolean isGlobalAsync = async != null && async;
handlerWrappers.forEach(hw -> {
final StateHandler<S> 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<S> params = new StateHandlerProcessParams<>(from, to, null);
if (runInAsync) {
if (executorToRun == null) {
throw new NullPointerException();
}
executorToRun.execute(() -> stateHandler.handle(params));
} else {
stateHandler.handle(params);
}
});
} }
} }

View File

@@ -11,7 +11,7 @@ import com.serliunx.statemanagement.manager.BidirectionalStateManager;
* <li> 切出指定状态时触发 (离开事件) * <li> 切出指定状态时触发 (离开事件)
* <li> 从A切换到B状态时触发 (交换事件) * <li> 从A切换到B状态时触发 (交换事件)
* <p> * <p>
* 请使用{@link StateMachineBuilder} 来构建状态机. * 请使用 {@link StateMachineBuilder} 来构建状态机.
* *
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a> * @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0 * @version 1.0.0
@@ -20,10 +20,17 @@ import com.serliunx.statemanagement.manager.BidirectionalStateManager;
* @see BidirectionalStateManager * @see BidirectionalStateManager
* @see com.serliunx.statemanagement.manager.StateManager * @see com.serliunx.statemanagement.manager.StateManager
*/ */
public interface StateMachine<S> extends BidirectionalStateManager<S> { public interface StateMachine<S> extends BidirectionalStateManager<S>, AutoCloseable {
/** /**
* 切换到指定状态 * 发布事件
*
* @param event 事件
*/
void publish(Object event);
/**
* 切换至指定状态
* <li> 在使用状态机的情况, 仅切换成功才会触发注册的各种事件. * <li> 在使用状态机的情况, 仅切换成功才会触发注册的各种事件.
* *
* @param state 新的状态 * @param state 新的状态

View File

@@ -18,7 +18,7 @@ public final class StateMachineBuilder<S> {
/** /**
* 状态管理器 * 状态管理器
*/ */
private List<S> stateList; private final List<S> stateList;
/** /**
* 执行器 * 执行器
*/ */
@@ -27,6 +27,10 @@ public final class StateMachineBuilder<S> {
* 是否异步执行 * 是否异步执行
*/ */
private Boolean async; private Boolean async;
/**
* 状态机类型
*/
private StateMachineType type = StateMachineType.STANDARD;
/** /**
* 各种事件 * 各种事件
@@ -35,8 +39,14 @@ public final class StateMachineBuilder<S> {
private final Map<S, List<StateHandlerWrapper<S>>> leaveHandlers = new HashMap<>(64); private final Map<S, List<StateHandlerWrapper<S>>> leaveHandlers = new HashMap<>(64);
private final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers = new HashMap<>(64); private final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers = new HashMap<>(64);
// private-ctor private StateMachineBuilder(List<S> states) {
private StateMachineBuilder() {} this.stateList = states;
}
private StateMachineBuilder(S[] states) {
this(Arrays.asList(states));
}
/** /**
* 添加交换事件 * 添加交换事件
@@ -189,18 +199,33 @@ public final class StateMachineBuilder<S> {
} }
/** /**
* 设置状态列表 * 指定状态机的类型
* <li> 状态机并发与否并不影响事件的执行逻辑
*
* @param type 类型
*/ */
public StateMachineBuilder<S> states(S[] states) { public StateMachineBuilder<S> type(StateMachineType type) {
return states(Arrays.asList(states)); if (type == null) {
throw new NullPointerException();
}
this.type = type;
return this;
} }
/** /**
* 设置状态列表 * 指定状态机的类型为标准型
* <li> 状态机并发与否并不影响事件的执行逻辑
*/ */
public StateMachineBuilder<S> states(List<S> states) { public StateMachineBuilder<S> standard() {
stateList = states; return type(StateMachineType.STANDARD);
return this; }
/**
* 指定状态机的类型为并发型
* <li> 状态机并发与否并不影响事件的执行逻辑
*/
public StateMachineBuilder<S> concurrent() {
return type(StateMachineType.CONCURRENT);
} }
/** /**
@@ -208,19 +233,33 @@ public final class StateMachineBuilder<S> {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <M extends StateMachine<S>> M build() { public <M extends StateMachine<S>> M build() {
return (M) new StandardStateMachine<>(stateList, entryHandlers, if (type == null) {
leaveHandlers, exchangeHandlers, executor, async); 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 状态机构建器实例 * @return 状态机构建器实例
* @param <S> 状态类参数
*/ */
@SuppressWarnings("all") public static <S> StateMachineBuilder<S> from(S[] states) {
public static <S> StateMachineBuilder<S> from(Class<? extends S> stateClass) { return new StateMachineBuilder<>(states);
return new StateMachineBuilder<>(); }
/**
* 状态机构建器
*
* @param states 状态集合
* @return 状态机构建器实例
*/
public static <S> StateMachineBuilder<S> from(List<S> states) {
return new StateMachineBuilder<>(states);
} }
} }

View File

@@ -0,0 +1,18 @@
package com.serliunx.statemanagement.machine;
/**
* 状态机类型
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @since 2024/12/31
*/
public enum StateMachineType {
/**
* 标准, 切换使用读写锁
*/
STANDARD,
/**
* 并发型, 切换使用CAS乐观锁
*/
CONCURRENT;
}

View File

@@ -19,26 +19,30 @@ import java.util.concurrent.Executors;
public class MachineTest { public class MachineTest {
@Test @Test
public void testStandardStateMachine() { public void testStandardStateMachine() throws Exception {
StateMachine<PrinterState> stateMachine = StateMachineBuilder.from(PrinterState.class) StateMachine<PrinterState> stateMachine = StateMachineBuilder.from(PrinterState.values())
.async(false) .async()
.states(PrinterState.values()) .standard()
.executor(Executors.newFixedThreadPool(16)) .executor(Executors.newFixedThreadPool(16))
.whenLeave(PrinterState.PRINTING, h -> { .whenLeave(PrinterState.PRINTING, h -> {
System.out.println(Thread.currentThread().getName() + ": leave PRINTING"); System.out.println(Thread.currentThread().getName() + ": leave PRINTING");
}) })
.whenEntry(PrinterState.SCANNING, h -> { .whenEntry(PrinterState.STOPPING, h -> {
System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo()); System.out.println(Thread.currentThread().getName() + ": entry STOPPING, from " + h.getFrom());
}) })
.whenEntry(PrinterState.PRINTING, h -> { .whenEntry(PrinterState.STOPPED, h -> {
System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo()); System.out.println(Thread.currentThread().getName() + ": entry STOPPED, from " + h.getFrom());
})
.exchange(PrinterState.STOPPED, PrinterState.IDLE, h -> {
System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo());
}) })
.build(); .build();
System.out.println(stateMachine.getClass());
stateMachine.switchTo(PrinterState.PRINTING); stateMachine.switchTo(PrinterState.PRINTING);
stateMachine.switchNext(); stateMachine.switchNext();
stateMachine.switchNext();
System.out.println(stateMachine.current());
stateMachine.close();
} }
} }