feat: 完善并发型状态机.

This commit is contained in:
2025-02-06 15:28:14 +08:00
parent 52946be558
commit 3a4db562ce
3 changed files with 108 additions and 11 deletions

View File

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

View File

@@ -9,6 +9,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
* 并发型状态机的默认实现, 内置的状态序列切换使用CAS实现.
*
* @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
* @since 2025/2/6 * @since 2025/2/6
@@ -32,11 +34,24 @@ public class DefaultConcurrentStateMachine<S> extends AbstractStateMachine<S> im
@Override @Override
public boolean compareAndSet(S expectedValue, S newValue) { 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 current = indexOf(expectedValue);
int newIndex = indexOf(newValue); int newIndex = indexOf(newValue);
if (current == -1 || newIndex == -1) if (current == -1 || newIndex == -1)
return false; return false;
return index.compareAndSet(current, newIndex);
S oldState = get(index.get());
boolean result = index.compareAndSet(current, newIndex);
if (result && invokeHandlers) {
S newState = get(index.get());
invokeHandlers(oldState, newState);
}
return result;
} }
/** /**
@@ -48,8 +63,11 @@ public class DefaultConcurrentStateMachine<S> extends AbstractStateMachine<S> im
public void reset(boolean invokeHandlers) { public void reset(boolean invokeHandlers) {
if (isDefault()) if (isDefault())
return; return;
S oldState = get(index.get());
exchangeToTarget(0); exchangeToTarget(0);
// TODO invokeHandlers S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
} }
@Override @Override
@@ -59,14 +77,17 @@ public class DefaultConcurrentStateMachine<S> extends AbstractStateMachine<S> im
i == index.get()) { i == index.get()) {
return false; return false;
} }
S oldState = get(index.get());
exchangeToTarget(i); exchangeToTarget(i);
if (invokeHandlers)
invokeHandlers(oldState, state);
return true; return true;
} }
@Override @Override
public S switchPrevAndGet(boolean invokeHandlers) { public S switchPrevAndGet(boolean invokeHandlers) {
S oldState = get(index.get()); S oldState = get(index.get());
exchangeToPrev();
S newState = get(index.get()); S newState = get(index.get());
if (invokeHandlers) if (invokeHandlers)
invokeHandlers(oldState, newState); invokeHandlers(oldState, newState);
@@ -75,27 +96,50 @@ public class DefaultConcurrentStateMachine<S> extends AbstractStateMachine<S> im
@Override @Override
public S getAndSwitchPrev(boolean invokeHandlers) { public S getAndSwitchPrev(boolean invokeHandlers) {
return super.getAndSwitchPrev(invokeHandlers); S oldState = get(index.get());
exchangeToPrev();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
return oldState;
} }
@Override @Override
public void switchPrev(boolean invokeHandlers) { public void switchPrev(boolean invokeHandlers) {
super.switchPrev(invokeHandlers); S oldState = get(index.get());
exchangeToPrev();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
} }
@Override @Override
public S switchNextAndGet(boolean invokeHandlers) { public S switchNextAndGet(boolean invokeHandlers) {
return super.switchNextAndGet(invokeHandlers); S oldState = get(index.get());
exchangeToNext();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
return newState;
} }
@Override @Override
public S getAndSwitchNext(boolean invokeHandlers) { public S getAndSwitchNext(boolean invokeHandlers) {
return super.getAndSwitchNext(invokeHandlers); S oldState = get(index.get());
exchangeToNext();
S newState =get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
return oldState;
} }
@Override @Override
public void switchNext(boolean invokeHandlers) { public void switchNext(boolean invokeHandlers) {
super.switchNext(invokeHandlers); S oldState = get(index.get());
exchangeToNext();
S newState = get(index.get());
if (invokeHandlers)
invokeHandlers(oldState, newState);
} }
@Override @Override
@@ -106,15 +150,32 @@ public class DefaultConcurrentStateMachine<S> extends AbstractStateMachine<S> im
/** /**
* 是否为默认状态 * 是否为默认状态
*/ */
private boolean isDefault() { protected boolean isDefault() {
return index.get() == 0; return index.get() == 0;
} }
/** /**
* 移动下标至上一个状态 * 移动下标至上一个状态
* <li> 使用CAS一直尝试, 直到成功
*/ */
public void exchangeToPrev() { protected void exchangeToPrev() {
final int size = size(); 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));
} }
/** /**
@@ -123,7 +184,7 @@ public class DefaultConcurrentStateMachine<S> extends AbstractStateMachine<S> im
* *
* @param target 目标值 * @param target 目标值
*/ */
private void exchangeToTarget(int target) { protected void exchangeToTarget(int target) {
int currentValue; int currentValue;
do { do {
currentValue = index.get(); currentValue = index.get();

View File

@@ -48,4 +48,18 @@ public class MachineTest {
stateMachine.close(); stateMachine.close();
} }
@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();
}
} }