change: 调整工程结构.

This commit is contained in:
2025-03-23 19:16:12 +08:00
parent 494f093041
commit f6a3b336de
32 changed files with 74 additions and 51 deletions

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.serliunx</groupId>
<artifactId>state-management</artifactId>
<version>1.0.0-alpha</version>
</parent>
<packaging>jar</packaging>
<artifactId>state-management-core</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@@ -0,0 +1,28 @@
package com.serliunx.statemanagement.core.exception;
/**
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public class StateException extends RuntimeException {
public StateException() {
}
public StateException(String message) {
super(message);
}
public StateException(String message, Throwable cause) {
super(message, cause);
}
public StateException(Throwable cause) {
super(cause);
}
public StateException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -0,0 +1,306 @@
package com.serliunx.statemanagement.core.machine;
import com.serliunx.statemanagement.core.machine.handler.StateHandler;
import com.serliunx.statemanagement.core.machine.handler.StateHandlerProcessParams;
import com.serliunx.statemanagement.core.machine.handler.StateHandlerWrapper;
import com.serliunx.statemanagement.core.manager.AbstractStateManager;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/**
* 状态机抽象实现, 实现最基本功能
*
* @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 StateMachineContext<S> context;
/**
* 默认的构造函数
*
* @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,
Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries,
Executor executor,
Boolean async
) {
super(stateList);
context = new StateMachineContext<>(entryHandlers, leaveHandlers, exchangeHandlers, eventRegistries, executor, async);
}
@Override
public void close() throws Exception {
final Executor executor = context.executor;
if (executor == null) {
return;
}
if (executor instanceof ExecutorService) {
ExecutorService es = (ExecutorService) executor;
es.shutdown();
if (!es.awaitTermination(10, TimeUnit.SECONDS)) {
es.shutdownNow();
}
} else if (executor instanceof AutoCloseable) {
AutoCloseable ac = (AutoCloseable) executor;
ac.close();
}
}
@Override
public void reset(boolean invokeHandlers) {
try {
writeLock.lock();
S oldState = get();
super.reset();
S newState = get();
if (invokeHandlers)
invokeHandlers(oldState, newState);
} finally {
writeLock.unlock();
}
}
@Override
public boolean switchTo(S state, boolean invokeHandlers) {
int i = indexOf(state);
if (i == -1 || i == currentIndex()) {
return false;
}
try {
writeLock.lock();
// 重新检查
if (i == currentIndex()) {
return false;
}
S oldState = get();
updateCurrentIndex(i);
S newState = get();
if (invokeHandlers)
invokeHandlers(oldState, newState);
return true;
} finally {
writeLock.unlock();
}
}
@Override
public S switchPrevAndGet(boolean invokeHandlers) {
try {
writeLock.lock();
S oldState = get();
prev();
S newState = get();
if (invokeHandlers)
invokeHandlers(oldState, newState);
return newState;
} finally {
writeLock.unlock();
}
}
@Override
public S getAndSwitchPrev(boolean invokeHandlers) {
try {
writeLock.lock();
S oldState = get();
prev();
S newState = get();
if (invokeHandlers)
invokeHandlers(oldState, newState);
return oldState;
} finally {
writeLock.unlock();
}
}
@Override
public void switchPrev(boolean invokeHandlers) {
try {
writeLock.lock();
S oldState = get();
prev();
S newState = get();
if (invokeHandlers)
invokeHandlers(oldState, newState);
} finally {
writeLock.unlock();
}
}
@Override
public S switchNextAndGet(boolean invokeHandlers) {
try {
writeLock.lock();
S oldState = get();
next();
S newState = get();
if (invokeHandlers)
invokeHandlers(oldState, newState);
return newState;
} finally {
writeLock.unlock();
}
}
@Override
public S getAndSwitchNext(boolean invokeHandlers) {
try {
writeLock.lock();
S oldState = get();
next();
S newState = get();
if (invokeHandlers)
invokeHandlers(oldState, newState);
return oldState;
} finally {
writeLock.unlock();
}
}
@Override
public void switchNext(boolean invokeHandlers) {
try {
writeLock.lock();
S oldState = get();
next();
S newState = get();
if (invokeHandlers)
invokeHandlers(oldState, newState);
} finally {
writeLock.unlock();
}
}
@Override
public void publish(Object event) {
List<Consumer<StateMachine<S>>> consumers = context.eventRegistries.get(event);
if (consumers == null ||
consumers.isEmpty()) {
return;
}
final Executor executor = context.executor;
final boolean async = context.async != null && context.async && executor != null;
consumers.forEach(consumer -> {
if (async)
executor.execute(() -> consumer.accept(this));
else
consumer.accept(this);
});
}
@Override
public S switchPrevAndGet() {
return switchPrevAndGet(true);
}
@Override
public S getAndSwitchPrev() {
return getAndSwitchPrev(true);
}
@Override
public void switchPrev() {
switchPrev(true);
}
@Override
public S switchNextAndGet() {
return switchNextAndGet(true);
}
@Override
public S getAndSwitchNext() {
return getAndSwitchNext(true);
}
@Override
public void switchNext() {
switchNext(true);
}
@Override
public boolean switchTo(S state) {
return switchTo(state, true);
}
@Override
public void reset() {
reset(true);
}
/**
* 触发处理器
*
* @param from 源状态
* @param to 目的状态
*/
protected final void invokeHandlers(S from, S to) {
// 触发离开处理器
doInvokeHandlers(context.leaveHandlers.get(from), from, to);
// 触发进入处理器
doInvokeHandlers(context.entryHandlers.get(to), from, to);
// 触发交换处理器
final String key = from.toString() + "-" + to.toString();
doInvokeHandlers(context.exchangeHandlers.get(key), from, to);
}
/**
* 触发
*/
private void doInvokeHandlers(List<StateHandlerWrapper<S>> handlerWrappers, S from, S to) {
if (handlerWrappers == null)
return;
handlerWrappers.forEach(hw -> {
final StateHandler<S> stateHandler;
if (hw == null ||
(stateHandler = hw.getStateHandler()) == null)
return;
final StateHandlerProcessParams<S> params = new StateHandlerProcessParams<>(from, to, null);
/*
* 一、异步逻辑校验: 首先判断是否需要异步执行状态处理器, 具体的状态逻辑处理器优先级大于全局
* 即: 如果全局指定了同步执行, 但此时特定的状态处理器注册时指定为异步执行的话. 该处理器
* 为异步执行.
*
* 二、 当确定了为异步执行时会选择合适的异步执行器(通常都是线程池), 如果状态处理器注册
* 时指定了异步执行器, 则优先使用该异步执行器;反则会使用全局的异步执行器。如果上一步骤
* 中确定为异步执行但当前步骤没有寻找到合适的异步执行器则会报空指针异常(当前版本不会出现)
*/
if (hw.getAsync() == null ?
(context.async != null && context.async) :
hw.getAsync()) {
final Executor executor;
if ((executor = hw.getExecutor() == null ?
context.executor : hw.getExecutor()) == null)
// 不应该发生
throw new Error();
executor.execute(() -> stateHandler.handle(params));
} else
stateHandler.handle(params);
});
}
}

View File

@@ -0,0 +1,33 @@
package com.serliunx.statemanagement.core.machine;
/**
* 基本行为与{@link StateMachine} 一致, 最大不同是切换状态不再使用直接的锁机制, 具体由实现类决定
* <li> 默认实现{@link DefaultConcurrentStateMachine}, 状态切换序列由CAS实现.
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2025/2/6
* @see DefaultConcurrentStateMachine
*/
public interface ConcurrentStateMachine<S> extends StateMachine<S> {
/**
* 尝试使用CAS更新状态
* <li> 无论是否成功更新都不触发状态处理器
*
* @param expectedValue 前置状态
* @param newValue 更新的状态值
* @return 成功更新返回真, 否则返回假
*/
boolean compareAndSet(S expectedValue, S newValue);
/**
* 尝试使用CAS更新状态
*
* @param expectedValue 前置状态
* @param newValue 更新的状态值
* @param invokeHandlers 是否触发状态处理器, 仅在成功更新时才触发
* @return 成功更新返回真, 否则返回假
*/
boolean compareAndSet(S expectedValue, S newValue, boolean invokeHandlers);
}

View File

@@ -0,0 +1,193 @@
package com.serliunx.statemanagement.core.machine;
import com.serliunx.statemanagement.core.machine.handler.StateHandlerWrapper;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
/**
* 并发型状态机的默认实现, 内置的状态序列切换使用CAS实现.
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2025/2/6
*/
public class DefaultConcurrentStateMachine<S> extends AbstractStateMachine<S> implements ConcurrentStateMachine<S> {
/**
* 当前状态
*/
private final AtomicInteger index = new AtomicInteger(0);
DefaultConcurrentStateMachine(List<S> stateList,
Map<S, List<StateHandlerWrapper<S>>> entryHandlers,
Map<S, List<StateHandlerWrapper<S>>> leaveHandlers,
Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers,
Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries,
Executor executor,
Boolean async) {
super(stateList, entryHandlers, leaveHandlers, exchangeHandlers, eventRegistries, executor, async);
}
@Override
public boolean compareAndSet(S expectedValue, S newValue) {
return compareAndSet(expectedValue, newValue, false);
}
@Override
public boolean compareAndSet(S expectedValue, S newValue, boolean invokeHandlers) {
int current = indexOf(expectedValue);
int newIndex = indexOf(newValue);
if (current == -1 || newIndex == -1)
return false;
S oldState = get(current);
boolean result = index.compareAndSet(current, newIndex);
if (result && invokeHandlers) {
S newState = get(newIndex);
invokeHandlers(oldState, newState);
}
return result;
}
/**
* 使用CAS不断尝试将当前状态重置回默认值(0)
*
* @param invokeHandlers 是否唤醒状态处理器
*/
@Override
public void reset(boolean invokeHandlers) {
if (isDefault())
return;
S oldState = get(index.get());
exchangeToTarget(0);
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
}
@Override
public boolean switchTo(S state, boolean invokeHandlers) {
int i = indexOf(state);
if (i == -1 ||
i == index.get()) {
return false;
}
S oldState = get(index.get());
exchangeToTarget(i);
if (invokeHandlers)
invokeHandlers(oldState, state);
return true;
}
@Override
public S switchPrevAndGet(boolean invokeHandlers) {
S oldState = get(index.get());
exchangeToPrev();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
return newState;
}
@Override
public S getAndSwitchPrev(boolean invokeHandlers) {
S oldState = get(index.get());
exchangeToPrev();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
return oldState;
}
@Override
public void switchPrev(boolean invokeHandlers) {
S oldState = get(index.get());
exchangeToPrev();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
}
@Override
public S switchNextAndGet(boolean invokeHandlers) {
S oldState = get(index.get());
exchangeToNext();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
return newState;
}
@Override
public S getAndSwitchNext(boolean invokeHandlers) {
S oldState = get(index.get());
exchangeToNext();
S newState =get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
return oldState;
}
@Override
public void switchNext(boolean invokeHandlers) {
S oldState = get(index.get());
exchangeToNext();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
}
@Override
public S current() {
return get(index.get());
}
/**
* 是否为默认状态
*/
protected boolean isDefault() {
return index.get() == 0;
}
/**
* 移动下标至上一个状态
* <li> 使用CAS一直尝试, 直到成功
*/
protected void exchangeToPrev() {
final int size = size();
int currentValue;
do {
currentValue = index.get();
} while (!index.compareAndSet(currentValue, currentValue == 0 ? size - 1 : currentValue - 1));
}
/**
* 移动下标至下一个状态
* <li> 使用CAS一直尝试, 直到成功
*/
protected void exchangeToNext() {
final int size = size();
int currentValue;
do {
currentValue = index.get();
} while (!index.compareAndSet(currentValue, currentValue == size - 1 ? 0 : currentValue + 1));
}
/**
* 切换到指定状态值
* <li> 使用CAS一直尝试, 直到成功
*
* @param target 目标值
*/
protected void exchangeToTarget(int target) {
int currentValue;
do {
currentValue = index.get();
} while (!index.compareAndSet(currentValue, target));
}
}

View File

@@ -0,0 +1,38 @@
package com.serliunx.statemanagement.core.machine;
import com.serliunx.statemanagement.core.machine.handler.StateHandlerWrapper;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* 状态机的标准实现
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public class StandardStateMachine<S> extends AbstractStateMachine<S> implements StateMachine<S> {
/**
* 默认的构造函数
*
* @param entryHandlers 进入事件处理器集合
* @param leaveHandlers 离开事件处理器集合
* @param exchangeHandlers 交换事件处理器集合
* @param executor 异步执行器
* @param async 是否异步执行
*/
StandardStateMachine(List<S> stateList,
Map<S, List<StateHandlerWrapper<S>>> entryHandlers,
Map<S, List<StateHandlerWrapper<S>>> leaveHandlers,
Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers,
Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries,
Executor executor,
Boolean async
) {
super(stateList, entryHandlers, leaveHandlers, exchangeHandlers, eventRegistries, executor, async);
}
}

View File

@@ -0,0 +1,107 @@
package com.serliunx.statemanagement.core.machine;
import com.serliunx.statemanagement.core.manager.StateManager;
import com.serliunx.statemanagement.core.manager.BidirectionalStateManager;
/**
* 状态机定义
* <p>
* 基于双向的状态管理器扩展 {@link BidirectionalStateManager}, 切换逻辑依赖于内置的状态管理器;
* 同时可以多种监听事件, 包括:
* <li> 切换至指定状态时触发 (进入事件)
* <li> 切出指定状态时触发 (离开事件)
* <li> 从A切换到B状态时触发 (交换事件)
* <p>
* 请使用 {@link StateMachineBuilder} 来构建状态机.
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
* @see StateMachineBuilder
* @see BidirectionalStateManager
* @see StateManager
*/
public interface StateMachine<S> extends BidirectionalStateManager<S>, AutoCloseable {
/**
* 切换至下一个状态
*
* @param invokeHandlers 是否唤醒状态处理器
*/
void switchNext(boolean invokeHandlers);
/**
* 返回并切换至下一个状态
*
* @param invokeHandlers 是否唤醒状态处理器
* @return 切换前的状态
*/
S getAndSwitchNext(boolean invokeHandlers);
/**
* 切换至下一个状态并返回切换后的状态
*
* @param invokeHandlers 是否唤醒状态处理器
* @return 切换后的状态
*/
S switchNextAndGet(boolean invokeHandlers);
/**
* 切换至上一个状态
*
* @param invokeHandlers 是否唤醒状态处理器
*/
void switchPrev(boolean invokeHandlers);
/**
* 获取当前状态并切换至上一个状态
*
* @param invokeHandlers 是否唤醒状态处理器
* @return 切换前的状态
*/
S getAndSwitchPrev(boolean invokeHandlers);
/**
* 切换至上一个状态并返回切换后的状态
*
* @param invokeHandlers 是否唤醒状态处理器
* @return 切换后的状态
*/
S switchPrevAndGet(boolean invokeHandlers);
/**
* 重置回默认状态, 一般为状态集合中的第一个
*
* @param invokeHandlers 是否唤醒状态处理器
*/
void reset(boolean invokeHandlers);
/**
* 切换至指定状态
* <li> 在使用状态机的情况, 仅切换成功才会触发注册的各种事件.
*
* @param invokeHandlers 是否唤醒状态处理器
* @param state 新的状态
* @return 切换成功返回真, 否则返回假
*/
boolean switchTo(S state, boolean invokeHandlers);
/**
* 发布事件
*
* @param event 事件
*/
void publish(Object event);
/**
* 切换至指定状态
* <li> 在使用状态机的情况, 仅切换成功才会触发注册的各种事件.
*
* @param state 新的状态
* @return 切换成功返回真, 否则返回假
*/
boolean switchTo(S state);
@Override
default void close() throws Exception {}
}

View File

@@ -0,0 +1,282 @@
package com.serliunx.statemanagement.core.machine;
import com.serliunx.statemanagement.core.machine.handler.StateHandler;
import com.serliunx.statemanagement.core.machine.handler.StateHandlerWrapper;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* 状态机构建
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public final class StateMachineBuilder<S> {
/**
* 状态管理器
*/
private final List<S> stateList;
/**
* 执行器
*/
private Executor executor;
/**
* 是否异步执行
*/
private Boolean async;
/**
* 状态机类型
*/
private StateMachineType type = StateMachineType.STANDARD;
/**
* 各种事件
*/
private final Map<S, List<StateHandlerWrapper<S>>> entryHandlers = 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<Object, List<Consumer<StateMachine<S>>>> eventRegistries = new HashMap<>(64);
private StateMachineBuilder(List<S> states) {
this.stateList = states;
}
private StateMachineBuilder(S[] states) {
this(Arrays.asList(states));
}
/**
* 添加交换事件
* <li> 从A状态切换至B状态时触发
*
* @param from 源状态
* @param to 目的状态
* @param handler 处理器
* @param async 是否异步执行
* @param executor 异步执行器, 异步执行时将使用, 不指定时将使用状态机内置的执行器
*/
public StateMachineBuilder<S> exchange(S from, S to, StateHandler<S> handler, Boolean async, Executor executor) {
final String key = from.toString() + "-" + to.toString();
final List<StateHandlerWrapper<S>> stateHandlerWrappers = exchangeHandlers.computeIfAbsent(key,
k -> new ArrayList<>());
stateHandlerWrappers.add(new StateHandlerWrapper<>(handler, executor, async));
return this;
}
/**
* 添加交换事件
* <li> 从A状态切换至B状态时触发
*
* @param from 源状态
* @param to 目的状态
* @param handler 处理器
* @param async 是否异步执行
*/
public StateMachineBuilder<S> exchange(S from, S to, StateHandler<S> handler, Boolean async) {
return exchange(from, to, handler, async, null);
}
/**
* 添加交换事件
* <li> 从A状态切换至B状态时触发
*
* @param from 源状态
* @param to 目的状态
* @param handler 处理器
*/
public StateMachineBuilder<S> exchange(S from, S to, StateHandler<S> handler) {
return exchange(from, to, handler, null);
}
/**
* 添加离开事件
* <li> 从指定状态切换到别的状态时执行的逻辑
*
* @param state 状态
* @param handler 处理逻辑
* @param async 是否异步执行
* @param executor 异步执行器, 异步执行时将使用, 不指定时将使用状态机内置的执行器
*/
public StateMachineBuilder<S> whenLeave(S state, StateHandler<S> handler, Boolean async, Executor executor) {
final List<StateHandlerWrapper<S>> stateHandlerWrappers = leaveHandlers.computeIfAbsent(state,
k -> new ArrayList<>());
stateHandlerWrappers.add(new StateHandlerWrapper<>(handler, executor, async));
return this;
}
/**
* 添加离开事件
* <li> 从指定状态切换到别的状态时执行的逻辑
*
* @param state 状态
* @param handler 处理逻辑
* @param async 是否异步执行
*/
public StateMachineBuilder<S> whenLeave(S state, StateHandler<S> handler, Boolean async) {
return whenLeave(state, handler, async, null);
}
/**
* 添加离开事件
* <li> 从指定状态切换到别的状态时执行的逻辑
*
* @param state 状态
* @param handler 处理逻辑
*/
public StateMachineBuilder<S> whenLeave(S state, StateHandler<S> handler) {
return whenLeave(state, handler, null);
}
/**
* 添加进入事件
* <li> 切换到了指定状态时执行的逻辑
*
* @param state 状态
* @param handler 处理逻辑
* @param async 是否异步执行
* @param executor 异步执行器, 异步执行时将使用, 不指定时将使用状态机内置的执行器
*/
public StateMachineBuilder<S> whenEntry(S state, StateHandler<S> handler, Boolean async, Executor executor) {
final List<StateHandlerWrapper<S>> stateHandlerWrappers = entryHandlers.computeIfAbsent(state,
k -> new ArrayList<>());
stateHandlerWrappers.add(new StateHandlerWrapper<>(handler, executor, async));
return this;
}
/**
* 添加进入事件
* <li> 切换到了指定状态时执行的逻辑
*
* @param state 状态
* @param handler 处理逻辑
* @param async 是否异步执行
*/
public StateMachineBuilder<S> whenEntry(S state, StateHandler<S> handler, Boolean async) {
return whenEntry(state, handler, async, null);
}
/**
* 添加进入事件
* <li> 切换到了指定状态时执行的逻辑
*
* @param state 状态
* @param handler 处理逻辑
*/
public StateMachineBuilder<S> whenEntry(S state, StateHandler<S> handler) {
return whenEntry(state, handler, null);
}
/**
* 注册当前状态机感兴趣的事件
*
* @param event 事件
* @param logic 切换逻辑
*/
public StateMachineBuilder<S> whenHappened(Object event, Consumer<StateMachine<S>> logic) {
List<Consumer<StateMachine<S>>> consumers = eventRegistries.computeIfAbsent(event, k -> new ArrayList<>());
consumers.add(logic);
return this;
}
/**
* 指定状态机的执行器
* <p>
* 优先级低于添加事件时指定的执行器
*
* @param executor 执行器
*/
public StateMachineBuilder<S> executor(Executor executor) {
this.executor = executor;
return this;
}
/**
* 定义状态机是否异步执行
*
* @param async 是否异步执行
*/
public StateMachineBuilder<S> async(Boolean async) {
this.async = async;
return this;
}
/**
* 定义状态机为异步执行
*/
public StateMachineBuilder<S> async() {
return async(true);
}
/**
* 指定状态机的类型
* <li> 状态机并发与否并不影响事件的执行逻辑
*
* @param type 类型
*/
public StateMachineBuilder<S> type(StateMachineType type) {
if (type == null) {
throw new NullPointerException();
}
this.type = type;
return this;
}
/**
* 指定状态机的类型为标准型
* <li> 状态机并发与否并不影响事件的执行逻辑
*/
public StateMachineBuilder<S> standard() {
return type(StateMachineType.STANDARD);
}
/**
* 指定状态机的类型为并发型
* <li> 状态机并发与否并不影响事件的执行逻辑
*/
public StateMachineBuilder<S> concurrent() {
return type(StateMachineType.CONCURRENT);
}
/**
* 构建
*/
@SuppressWarnings("unchecked")
public <M extends StateMachine<S>> M build() {
if (type == null) {
throw new NullPointerException();
}
if (type.equals(StateMachineType.STANDARD)) {
return (M)new StandardStateMachine<>(stateList, entryHandlers,
leaveHandlers, exchangeHandlers, eventRegistries, executor, async);
} else if (type.equals(StateMachineType.CONCURRENT)) {
return (M)new DefaultConcurrentStateMachine<>(stateList, entryHandlers,
leaveHandlers, exchangeHandlers, eventRegistries, executor, async);
}
throw new IllegalArgumentException("未知的状态机类型: " + type);
}
/**
* 状态机构建器
*
* @param states 状态集合
* @return 状态机构建器实例
*/
public static <S> StateMachineBuilder<S> from(S[] states) {
return new StateMachineBuilder<>(states);
}
/**
* 状态机构建器
*
* @param states 状态集合
* @return 状态机构建器实例
*/
public static <S> StateMachineBuilder<S> from(List<S> states) {
return new StateMachineBuilder<>(states);
}
}

View File

@@ -0,0 +1,70 @@
package com.serliunx.statemanagement.core.machine;
import com.serliunx.statemanagement.core.support.DefaultCountableRejectedExecutionHandler;
import com.serliunx.statemanagement.core.machine.handler.StateHandlerWrapper;
import com.serliunx.statemanagement.core.support.ExecutorUtils;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2025/2/2
*/
public final class StateMachineContext<S> {
/**
* 进入事件集合
*/
final Map<S, List<StateHandlerWrapper<S>>> entryHandlers;
/**
* 离开事件集合
*/
final Map<S, List<StateHandlerWrapper<S>>> leaveHandlers;
/**
* 交换事件集合
*/
final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers;
/**
* 事件注册集合
*/
final Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries;
/**
* 异步执行器
*/
final Executor executor;
/**
* 是否异步执行
* <p>
* 当具体的执行器没有指定是否异步时, 将根据该值决定是否异步执行.
*/
final Boolean async;
StateMachineContext(Map<S, List<StateHandlerWrapper<S>>> entryHandlers,
Map<S, List<StateHandlerWrapper<S>>> leaveHandlers,
Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers,
Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries,
Executor executor,
Boolean async
) {
this.entryHandlers = entryHandlers;
this.leaveHandlers = leaveHandlers;
this.exchangeHandlers = exchangeHandlers;
this.executor = executorAutoConfiguration(executor);
this.async = async;
this.eventRegistries = eventRegistries;
}
/**
* 执行器为空时自动创建一个适合当前操作系统的执行器(线程池)
*/
private Executor executorAutoConfiguration(Executor source) {
if (source == null) {
return ExecutorUtils.adaptiveThreadPool(new DefaultCountableRejectedExecutionHandler());
}
return source;
}
}

View File

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

View File

@@ -0,0 +1,21 @@
package com.serliunx.statemanagement.core.machine.handler;
/**
* 状态处理器
* <p>
* 定义状态进入、离开及切换时执行的逻辑
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
@FunctionalInterface
public interface StateHandler<S> {
/**
* 处理
*
* @param params 参数
*/
void handle(StateHandlerProcessParams<S> params);
}

View File

@@ -0,0 +1,51 @@
package com.serliunx.statemanagement.core.machine.handler;
/**
* 状态处理器入参
* <p>
* 用于状态机处理事件
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
@SuppressWarnings("all")
public final class StateHandlerProcessParams<S> {
/**
* 源状态
*/
private final S from;
/**
* 目标状态
*/
private final S to;
/**
* 附加参数
*/
private final Object attach;
/**
* @param from 原状态
* @param to 目标状态
* @param attach 附加参数
* @param bidirectionalStateManager 状态机内置的状态管理器
*/
public StateHandlerProcessParams(S from, S to, Object attach) {
this.from = from;
this.to = to;
this.attach = attach;
}
public S getFrom() {
return from;
}
public S getTo() {
return to;
}
public Object getAttach() {
return attach;
}
}

View File

@@ -0,0 +1,10 @@
package com.serliunx.statemanagement.core.machine.handler;
/**
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public class StateHandlerRegistry {
}

View File

@@ -0,0 +1,53 @@
package com.serliunx.statemanagement.core.machine.handler;
import java.util.concurrent.Executor;
/**
* 处理器封装
* <p>
* 用于添加处理器时设置处理器的行为
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
@SuppressWarnings("all")
public final class StateHandlerWrapper<S> {
/**
* 状态处理器
*/
private final StateHandler<S> stateHandler;
/**
* 执行器
* <li> 用于异步执行处理逻辑
*/
private final Executor executor;
/**
* 是否异步执行
*/
private final Boolean async;
/**
* @param stateHandler 状态处理器
* @param executor 执行器
* @param async 是否异步执行
*/
public StateHandlerWrapper(StateHandler<S> stateHandler, Executor executor, Boolean async) {
this.stateHandler = stateHandler;
this.executor = executor;
this.async = async;
}
public StateHandler<S> getStateHandler() {
return stateHandler;
}
public Executor getExecutor() {
return executor;
}
public Boolean getAsync() {
return async;
}
}

View File

@@ -0,0 +1,208 @@
package com.serliunx.statemanagement.core.manager;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 状态管理器的抽象实现
* <p>
* 提供了最基本功能的实现以及部分供子类使用的参数,如:锁、当前状态的序号等.
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public abstract class AbstractStateManager<S> implements StateManager<S> {
/**
* 状态列表
*/
private final List<S> stateList;
/**
* 当前状态的序号
* <p> 请保证仅在有写锁的情况下去修改
*/
private volatile int index;
/**
* 锁
*/
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
/**
* 读锁
*/
protected final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
/**
* 写锁
*/
protected final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
/**
* @param stateList 状态列表
*/
public AbstractStateManager(List<S> stateList) {
this.stateList = stateList;
index = 0;
}
/**
* @param states 状态数组
*/
public AbstractStateManager(S[] states) {
this(Arrays.asList(states));
}
/**
* 保留空构造器
*/
public AbstractStateManager() {
this((List<S>) null);
}
@Override
public S current() {
try {
readLock.lock();
return get();
} finally {
readLock.unlock();
}
}
@Override
public boolean switchTo(S state) {
int i = indexOf(state);
if (i == -1 || i == index) {
return false;
}
try {
writeLock.lock();
// 重新检查
if (i == index) {
return false;
}
index = i;
} finally {
writeLock.unlock();
}
return true;
}
@Override
public void reset() {
try {
writeLock.lock();
index = getDefault();
} finally {
writeLock.unlock();
}
}
@Override
public int size() {
return stateList.size();
}
@Override
public boolean isSwitchable() {
return stateList.size() > 1;
}
/**
* 将序号移动至下一个
* <li> 自动归零
* <li> 仅在持有写锁的情况下访问
*/
@SuppressWarnings("all")
protected void next() {
if (++index >= stateList.size())
index = 0;
}
/**
* 将序号移动至上一个
* <li> 自动归零
* <li> 仅在持有写锁的情况下访问
*/
@SuppressWarnings("all")
protected void prev() {
if (--index < 0)
index = 0;
}
/**
* 获取当前状态
* <p>
* 类及子类访问当前状态时不允许使用{@link #current()},因为会造成死锁
*
* <li> 仅在持有锁的情况下访问
*
* @return 当前状态
*/
protected S get() {
return stateList.get(index);
}
/**
* 获取指定下标的状态
*
* @param index 下标
* @return 状态
*/
protected S get(int index) {
return stateList.get(index);
}
/**
* 获取指定状态在状态列表中的序号
*
* @param state 状态
* @return 序号 {@link List#indexOf(Object)}
*/
protected int indexOf(S state) {
return stateList.indexOf(state);
}
/**
* 判断当前状态是否为状态列表中的最后一个
*
* @return 是最后一个时返回真, 否则返回假.
*/
protected boolean isLast() {
return index == stateList.size() - 1;
}
/**
* 判断当前状态是否为状态列表中的第一个
*
* @return 是第一个时返回真, 否则返回假.
*/
protected boolean isFirst() {
return index == getDefault();
}
/**
* 获取当前状态的序号
*
* @return 当前状态序号
*/
protected int currentIndex() {
return index;
}
/**
* 更新当前状态的序号
*/
protected void updateCurrentIndex(int newIndex) {
index = newIndex;
}
/**
* 状态序号默认值(等同于默认状态)
*/
protected int getDefault() {
return 0;
}
}

View File

@@ -0,0 +1,32 @@
package com.serliunx.statemanagement.core.manager;
/**
* 双向流转的状态管理器
* <p>
* 基于单向流转的状态管理器{@link UnidirectionalStateManager} 实现, 在其基础上允许了反方向切换状态
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public interface BidirectionalStateManager<S> extends UnidirectionalStateManager<S> {
/**
* 切换至上一个状态并返回切换后的状态
*
* @return 切换后的状态
*/
S switchPrevAndGet();
/**
* 获取当前状态并切换至上一个状态
*
* @return 切换前的状态
*/
S getAndSwitchPrev();
/**
* 切换至上一个状态
*/
void switchPrev();
}

View File

@@ -0,0 +1,98 @@
package com.serliunx.statemanagement.core.manager;
import com.serliunx.statemanagement.core.exception.StateException;
import java.util.List;
/**
* 断路的单向状态管理器
* <p> 逻辑与{@link UnidirectionalStateManager}大体相同, 不同的点在于:
* <li> 最后一个状态无法转向第一个状态, 即为一次性的状态管理器.
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2025/1/13
*/
public final class BreakageUnidirectionalStateManager<S> extends DefaultUnidirectionalStateManager<S> {
/**
* 是否在切换失败时抛出异常
*/
private final boolean allowThrow;
public BreakageUnidirectionalStateManager(List<S> stateList, boolean allowThrow) {
super(stateList);
this.allowThrow = allowThrow;
}
public BreakageUnidirectionalStateManager(S[] states, boolean allowThrow) {
super(states);
this.allowThrow = allowThrow;
}
public BreakageUnidirectionalStateManager(List<S> stateList) {
this(stateList, true);
}
public BreakageUnidirectionalStateManager(S[] states) {
this(states, true);
}
@Override
public S switchNextAndGet() {
if (isLast()) {
if (allowThrow)
throw new StateException("The last state has been reached and cannot be switched again!");
return null;
}
return super.switchNextAndGet();
}
@Override
public S getAndSwitchNext() {
if (isLast()) {
if (allowThrow)
throw new StateException("The last state has been reached and cannot be switched again!");
return null;
}
return super.getAndSwitchNext();
}
@Override
public void switchNext() {
if (isLast()) {
if (allowThrow)
throw new StateException("The last state has been reached and cannot be switched again!");
return;
}
super.switchNext();
}
@Override
public boolean switchTo(S state) {
/*
* 非最后一个状态且切换后的状态必须在当前状态的下位
*/
if (indexOf(state) <= currentIndex()) {
if (allowThrow)
throw new StateException("The last state has been reached and cannot be switched again!");
return false;
}
return super.switchTo(state);
}
@Override
public boolean isCircle() {
return false;
}
@Override
public void reset() {
throw new UnsupportedOperationException("Cannot reset state for BreakageUnidirectionalStateManager!");
}
@Override
public boolean isSwitchable() {
return !isLast();
}
}

View File

@@ -0,0 +1,21 @@
package com.serliunx.statemanagement.core.manager;
/**
* 将指定状态管理器标记为循环的状态管理器
* <li> 允许单向、双向循环
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2025/1/13
*/
public interface CircleStateManager {
/**
* 是否为循环的状态管理器
*
* @return 属于循环状态管理器返回真, 否则返回假.
*/
default boolean isCircle() {
return true;
}
}

View File

@@ -0,0 +1,66 @@
package com.serliunx.statemanagement.core.manager;
import java.util.List;
/**
* 双向流转的状态管理器的默认实现
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public class DefaultBidirectionalStateManager<S> extends DefaultUnidirectionalStateManager<S>
implements BidirectionalStateManager<S> {
/**
* @param stateList 状态列表
*/
public DefaultBidirectionalStateManager(List<S> stateList) {
super(stateList);
}
/**
* @param states 状态数组
*/
public DefaultBidirectionalStateManager(S[] states) {
super(states);
}
@Override
public S switchPrevAndGet() {
try {
writeLock.lock();
prev();
return get();
} finally {
writeLock.unlock();
}
}
@Override
public S getAndSwitchPrev() {
try {
writeLock.lock();
S current = get();
prev();
return current;
} finally {
writeLock.unlock();
}
}
@Override
public void switchPrev() {
try {
writeLock.lock();
prev();
} finally {
writeLock.unlock();
}
}
@Override
public boolean switchTo(S state) {
return defaultSwitchTo(state);
}
}

View File

@@ -0,0 +1,90 @@
package com.serliunx.statemanagement.core.manager;
import java.util.List;
/**
* 单向流转的状态管理器的默认实现
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public class DefaultUnidirectionalStateManager<S> extends AbstractStateManager<S>
implements UnidirectionalStateManager<S> {
/**
* @param stateList 状态列表
*/
public DefaultUnidirectionalStateManager(List<S> stateList) {
super(stateList);
}
/**
* @param states 状态数组
*/
public DefaultUnidirectionalStateManager(S[] states) {
super(states);
}
@Override
public S switchNextAndGet() {
try {
writeLock.lock();
next();
return get();
} finally {
writeLock.unlock();
}
}
@Override
public S getAndSwitchNext() {
try {
writeLock.lock();
S current = get();
next();
return current;
} finally {
writeLock.unlock();
}
}
@Override
public void switchNext() {
try {
writeLock.lock();
next();
} finally {
writeLock.unlock();
}
}
@Override
public boolean switchTo(S state) {
final int i;
if ((i = indexOf(state)) == -1 ||
i == currentIndex()) {
return false;
}
try {
writeLock.lock();
final boolean isLast;
if (i == currentIndex() ||
(!(isLast = isLast()) && i < currentIndex()) ||
(isLast && i != getDefault())) {
return false;
}
updateCurrentIndex(i);
} finally {
writeLock.unlock();
}
return true;
}
/**
* 保留默认的切换方式供子类使用
*/
protected boolean defaultSwitchTo(S state) {
return super.switchTo(state);
}
}

View File

@@ -0,0 +1,27 @@
package com.serliunx.statemanagement.core.manager;
import java.util.List;
/**
* 最简单的状态管理器实现
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public final class StandardStateManager<S> extends AbstractStateManager<S> {
/**
* @param stateList 状态列表
*/
public StandardStateManager(List<S> stateList) {
super(stateList);
}
/**
* @param states 状态数组
*/
public StandardStateManager(S[] states) {
super(states);
}
}

View File

@@ -0,0 +1,48 @@
package com.serliunx.statemanagement.core.manager;
/**
* 状态管理器
* <p>
* 将状态集合按照一定的逻辑流转
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public interface StateManager<S> {
/**
* 获取当前状态
*
* @return 当前最新状态
*/
S current();
/**
* 切换到指定状态
*
* @param state 新的状态
* @return 切换成功返回真, 否则返回假
*/
boolean switchTo(S state);
/**
* 重置回默认状态, 一般为状态集合中的第一个
*/
void reset();
/**
* 获取当前状态数量
* @return 数量
*/
int size();
/**
* 是否可切换
*
* @return 可切换返回真, 否则返回假
*/
default boolean isSwitchable() {
return true;
}
}

View File

@@ -0,0 +1,40 @@
package com.serliunx.statemanagement.core.manager;
/**
* 单向流转的状态管理器
* <p>
* 其基本逻辑等同于 {@link StateManager}, 但存在以下不同:
* <li> 状态只能单方向流动(最后一个状态允许切换至第一个状态), 如果有A, B, C, D 四种状态则存在以下几种情况:
* <p>
* <p>
* <li> A -> B 允许直接切换, A -> C 允许直接切换, C -> D 允许直接切换 等等..
* <li> B -> A 不允许切换, C -> A 不允许切换, D -> C 不允许切换 等等..
* <li> 特例: D -> A 是允许的, 因为D是最后一个状态, 故可以切换至第一个状态.
* <p>
* 即状态的切换只允许一个方向,不允许向前流动,除非到达最后一个状态!
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public interface UnidirectionalStateManager<S> extends StateManager<S>, CircleStateManager {
/**
* 切换至下一个状态并返回切换后的状态
*
* @return 切换后的状态
*/
S switchNextAndGet();
/**
* 返回并切换至下一个状态
*
* @return 切换前的状态
*/
S getAndSwitchNext();
/**
* 切换至下一个状态
*/
void switchNext();
}

View File

@@ -0,0 +1,27 @@
package com.serliunx.statemanagement.core.support;
import java.util.concurrent.RejectedExecutionHandler;
/**
* 附带计数的拒绝策略
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2025/3/5
*/
public interface CountableRejectedExecutionHandler extends RejectedExecutionHandler {
/**
* 获取当前拒绝的任务数量
*
* @return 当目前为止所拒绝的任务数量
*/
long getCount();
/**
* 获取最后一次被拒绝的任务
*
* @return 最后一次被拒绝的任务
*/
Runnable getLastRejectedTask();
}

View File

@@ -0,0 +1,40 @@
package com.serliunx.statemanagement.core.support;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
/**
* 附带计数的拒绝策略默认实现(丢弃任务并计数)
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2025/3/5
*/
public class DefaultCountableRejectedExecutionHandler implements CountableRejectedExecutionHandler {
/**
* 计数器
*/
private final AtomicLong counter = new AtomicLong(0);
/**
* 最后一次被拒绝的任务
*/
private volatile Runnable last = null;
@Override
public long getCount() {
return counter.get();
}
@Override
public Runnable getLastRejectedTask() {
return last;
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
last = r;
counter.incrementAndGet();
}
}

View File

@@ -0,0 +1,29 @@
package com.serliunx.statemanagement.core.support;
import java.util.concurrent.*;
/**
* 线程池相关工具类
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public final class ExecutorUtils {
private ExecutorUtils() {throw new UnsupportedOperationException();}
/**
* 快速获取自适应参数的线程池
* <li> 核心线程数量为当前处理器数量的两倍; 最大线程数量为当前处理器数量的四倍.
*
* @return 执行器(线程池)
*/
public static Executor adaptiveThreadPool(RejectedExecutionHandler rejectedExecutionHandler) {
final int processors = Runtime.getRuntime().availableProcessors();
return new ThreadPoolExecutor(processors * 2, processors * 4, 5,
TimeUnit.MINUTES, new ArrayBlockingQueue<>(processors * 8),
new NamedThreadFactory("state-process-%s"), rejectedExecutionHandler);
}
}

View File

@@ -0,0 +1,26 @@
package com.serliunx.statemanagement.core.support;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 模板名称线程池
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @since 2025/2/17
*/
public final class NamedThreadFactory implements ThreadFactory {
private final AtomicInteger threadNumber = new AtomicInteger(0);
private final String namePattern;
public NamedThreadFactory(String namePattern) {
this.namePattern = namePattern;
}
@Override
public Thread newThread(Runnable r) {
return new Thread(r, String.format(namePattern, threadNumber.getAndIncrement()));
}
}

View File

@@ -0,0 +1,58 @@
package com.serliunx.statemanagement;
import com.serliunx.statemanagement.core.machine.ConcurrentStateMachine;
import com.serliunx.statemanagement.core.machine.StateMachine;
import com.serliunx.statemanagement.core.machine.StateMachineBuilder;
import com.serliunx.statemanagement.support.PrinterEvent;
import com.serliunx.statemanagement.support.PrinterState;
import org.junit.Test;
/**
* 状态机测试
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public class MachineTest {
@Test
public void testStandardStateMachine() throws Exception {
StateMachine<PrinterState> stateMachine = StateMachineBuilder.from(PrinterState.values())
.async(true)
.standard()
.whenLeave(PrinterState.IDLE, h -> {
System.out.println(Thread.currentThread().getName() + ": leave IDLE");
})
.whenEntry(PrinterState.STOPPING, h -> {
System.out.println(Thread.currentThread().getName() + ": entry STOPPING, from " + h.getFrom());
})
.whenEntry(PrinterState.STOPPED, h -> {
System.out.println(Thread.currentThread().getName() + ": entry STOPPED, from " + h.getFrom());
})
.whenHappened(PrinterEvent.TURN_ON, m -> {
m.switchTo(PrinterState.SCANNING);
})
.whenHappened(PrinterEvent.TURN_OFF, m -> {
if (m.switchTo(PrinterState.STOPPING))
m.switchTo(PrinterState.STOPPED);
})
.build();
stateMachine.publish(PrinterEvent.TURN_ON);
}
@Test
public void testConcurrentStateMachine() throws Exception {
ConcurrentStateMachine<PrinterState> stateMachine = StateMachineBuilder.from(PrinterState.values())
.whenEntry(PrinterState.STOPPING, h -> {
System.out.println(1111);
})
.concurrent()
.build();
System.out.println(stateMachine.compareAndSet(PrinterState.IDLE, PrinterState.STOPPING, true));
stateMachine.close();
}
}

View File

@@ -0,0 +1,36 @@
package com.serliunx.statemanagement;
import com.serliunx.statemanagement.core.manager.BreakageUnidirectionalStateManager;
import com.serliunx.statemanagement.core.manager.DefaultUnidirectionalStateManager;
import com.serliunx.statemanagement.core.manager.UnidirectionalStateManager;
import com.serliunx.statemanagement.support.PrinterState;
import org.junit.Test;
/**
* 状态管理器测试
*
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public class ManagerTest {
@Test
public void testUnidirectionalStateManager() {
UnidirectionalStateManager<PrinterState> unidirectionalStateManager =
new DefaultUnidirectionalStateManager<>(PrinterState.values());
System.out.println(unidirectionalStateManager.switchTo(PrinterState.IDLE));
System.out.println(unidirectionalStateManager.switchTo(PrinterState.SCANNING));
}
@Test
public void testBreakageUnidirectionalStateManager() {
UnidirectionalStateManager<PrinterState> bum = new BreakageUnidirectionalStateManager<>(PrinterState.values());
while (bum.isSwitchable()) {
System.out.println(bum.getAndSwitchNext());
}
System.out.println(bum.current());
}
}

View File

@@ -0,0 +1,12 @@
package com.serliunx.statemanagement.support;
/**
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @since 2025/1/24
*/
public enum PrinterEvent {
TURN_ON,
TURN_OFF,
}

View File

@@ -0,0 +1,14 @@
package com.serliunx.statemanagement.support;
/**
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @version 1.0.0
* @since 2024/12/28
*/
public enum PrinterState {
IDLE,
SCANNING,
PRINTING,
STOPPING,
STOPPED
}