change: 代码整理、定向切换时校验当前状态.

This commit is contained in:
2024-12-31 09:21:03 +08:00
parent 682266b591
commit 5fed1bbf19
9 changed files with 46 additions and 15 deletions

View File

@@ -149,8 +149,16 @@ public class StandardStateMachine<S> extends AbstractStateManager<S> implements
@Override @Override
public boolean switchTo(S state) { public boolean switchTo(S state) {
int i = indexOf(state);
if (i == -1 || i == currentIndex()) {
return false;
}
try { try {
writeLock.lock(); writeLock.lock();
// 重新检查
if (i == currentIndex()) {
return false;
}
S oldState = get(); S oldState = get();
boolean result = super.switchTo(state); boolean result = super.switchTo(state);
if (result) { if (result) {

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
@@ -22,5 +22,12 @@ import com.serliunx.statemanagement.manager.BidirectionalStateManager;
*/ */
public interface StateMachine<S> extends BidirectionalStateManager<S> { public interface StateMachine<S> extends BidirectionalStateManager<S> {
/**
* 切换到指定状态
* <li> 在使用状态机的情况, 仅切换成功才会触发注册的各种事件.
*
* @param state 新的状态
* @return 切换成功返回真, 否则返回假
*/
boolean switchTo(S state);
} }

View File

@@ -2,7 +2,6 @@ package com.serliunx.statemanagement.machine;
import com.serliunx.statemanagement.machine.handler.StateHandler; import com.serliunx.statemanagement.machine.handler.StateHandler;
import com.serliunx.statemanagement.machine.handler.StateHandlerWrapper; import com.serliunx.statemanagement.machine.handler.StateHandlerWrapper;
import com.serliunx.statemanagement.manager.BidirectionalStateManager;
import java.util.*; import java.util.*;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;

View File

@@ -1,7 +1,5 @@
package com.serliunx.statemanagement.machine.handler; package com.serliunx.statemanagement.machine.handler;
import com.serliunx.statemanagement.manager.BidirectionalStateManager;
/** /**
* 状态处理器入参 * 状态处理器入参
* <p> * <p>

View File

@@ -74,11 +74,15 @@ public abstract class AbstractStateManager<S> implements StateManager<S> {
@Override @Override
public boolean switchTo(S state) { public boolean switchTo(S state) {
int i = indexOf(state); int i = indexOf(state);
if (i == -1) { if (i == -1 || i == index) {
return false; return false;
} }
try { try {
writeLock.lock(); writeLock.lock();
// 重新检查
if (i == index) {
return false;
}
index = i; index = i;
} finally { } finally {
writeLock.unlock(); writeLock.unlock();

View File

@@ -61,11 +61,18 @@ public class DefaultUnidirectionalStateManager<S> extends AbstractStateManager<S
@Override @Override
public boolean switchTo(S state) { public boolean switchTo(S state) {
try {
writeLock.lock();
final int i; final int i;
if ((i = indexOf(state)) == -1 || if ((i = indexOf(state)) == -1 ||
(!isLast() && i < currentIndex()) || i == currentIndex()) {
return false;
}
try {
writeLock.lock();
// 重新检查
if (i == currentIndex()) {
return false;
}
if ((!isLast() && i < currentIndex()) ||
(isLast() && i != getDefault())) { (isLast() && i != getDefault())) {
return false; return false;
} }

View File

@@ -1,7 +1,5 @@
package com.serliunx.statemanagement.manager; package com.serliunx.statemanagement.manager;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/** /**
* 状态管理器 * 状态管理器
* <p> * <p>

View File

@@ -22,20 +22,23 @@ public class MachineTest {
public void testStandardStateMachine() { public void testStandardStateMachine() {
StateMachine<PrinterState> stateMachine = StateMachineBuilder.from(PrinterState.class) StateMachine<PrinterState> stateMachine = StateMachineBuilder.from(PrinterState.class)
.async(false) .async(false)
.states(PrinterState.values())
.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");
}) })
.states(PrinterState.values())
.executor(Executors.newFixedThreadPool(16))
.whenEntry(PrinterState.SCANNING, h -> { .whenEntry(PrinterState.SCANNING, h -> {
System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo()); System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo());
}, false) })
.whenEntry(PrinterState.PRINTING, h -> { .whenEntry(PrinterState.PRINTING, h -> {
System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo()); System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo());
}, false, Executors.newFixedThreadPool(1)) })
.exchange(PrinterState.STOPPED, PrinterState.IDLE, h -> { .exchange(PrinterState.STOPPED, PrinterState.IDLE, h -> {
System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo()); System.out.println(Thread.currentThread().getName() + ": " + h.getFrom() + " >>> " + h.getTo());
}) })
.build(); .build();
stateMachine.switchTo(PrinterState.PRINTING);
stateMachine.switchNext();
} }
} }

View File

@@ -1,5 +1,8 @@
package com.serliunx.statemanagement; package com.serliunx.statemanagement;
import com.serliunx.statemanagement.manager.DefaultUnidirectionalStateManager;
import com.serliunx.statemanagement.manager.UnidirectionalStateManager;
import com.serliunx.statemanagement.support.PrinterState;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Test; import org.junit.Test;
@@ -15,6 +18,10 @@ public class ManagerTest {
@Test @Test
public void testUnidirectionalStateManager() { public void testUnidirectionalStateManager() {
UnidirectionalStateManager<PrinterState> unidirectionalStateManager =
new DefaultUnidirectionalStateManager<>(PrinterState.values());
System.out.println(unidirectionalStateManager.switchTo(PrinterState.IDLE));
System.out.println(unidirectionalStateManager.switchTo(PrinterState.SCANNING));
} }
} }