我正在写一个java模拟应用程序,它有很多要模拟的实体。这些实体中的每一个在系统中随时都有一定的状态。对这种实体建模的一种可能的自然方法是使用state (or state machine)模式。问题是,如果有很多状态切换,它会在运行时创建大量对象,这可能会导致系统性能不佳。我有什么设计方案?我希望性能成为可维护性之后的主要标准。java中高效的状态机模式
感谢
我正在写一个java模拟应用程序,它有很多要模拟的实体。这些实体中的每一个在系统中随时都有一定的状态。对这种实体建模的一种可能的自然方法是使用state (or state machine)模式。问题是,如果有很多状态切换,它会在运行时创建大量对象,这可能会导致系统性能不佳。我有什么设计方案?我希望性能成为可维护性之后的主要标准。java中高效的状态机模式
感谢
我的建议:
您是否可以配置“转换管理”(即通过XML)。
将XML加载到存储状态的存储库。
内部数据结构将是一个地图:
Map<String,Map<String,Pair<String,StateChangeHandler>>> transitions;
原因我选择的是,这将是一个国家的名字
地图要地图“输入”,新规定:
每个地图定义可能的输入,并导致其由国家名称和StateChangeHandler我将详细阐述定义的新状态之间的映射,后来在库
改变状态的方法将有一个签名:
void changeState(StateOwner owner, String input)
通过这种方式,存储库在状态所有者使用它的意义上是无状态的,您可以复制一个副本
而不用担心线程安全问题。
StateOwner将成为您需要状态改变的类应该实现的接口。
我认为界面应该是这样的:
public interace StateOwner {
String getState();
void String setState(String newState);
}
此外,你将有一个ChangeStateHandler接口:
public interface StateChangeHandler {
void onChangeState(StateOwner, String newState) {
}
}
当仓库的改变状态的方法被调用时,它会
检查在数据结构上,stateOwner的当前状态具有“输入”的映射。 如果它有这样一个映射,它将检查输入是否有一个新的状态改变,并调用onChangeState方法。
我会建议你有一个StateChangeHandler的默认实现,当然还有子类,它们会更明确地定义状态变化行为。
正如我前面提到的,所有这些都可以从XML配置中加载,并且使用反射可以基于它们的名称(如XML中提到的)立即对StateChangeHandler对象进行实时处理,并将保存在存储库中。
效率和良好的性能依赖和获得使用以下几点:
a。存储库本身是无状态的 - 不应该保留StateOwner的内部引用。
b。您在系统启动时加载一次XML,然后在内存数据结构中进行处理。
c。您只会在需要时提供特定的StateChangeHandler实现,默认实现应该基本不做任何事情。
d。没有必要实例化处理程序的新对象(因为它们应该是无状态的)
这个建议是不是普遍的,它不是UML compliant但simple thing, it's a simple mean。
import java.util.HashMap;
import java.util.Map;
class Mobile1
{
enum State {
FIRST, SECOND, THIRD
}
enum Event {
FIRST, SECOND, THIRD
}
public Mobile1() { // initialization may be done by loading a file
Map< Event, State > tr;
tr = new HashMap<>();
tr.put(Event.FIRST, State.SECOND);
_fsm.put(State.FIRST, tr);
tr = new HashMap<>();
tr.put(Event.SECOND, State.THIRD);
_fsm.put(State.SECOND, tr);
tr = new HashMap<>();
tr.put(Event.THIRD, State.FIRST);
_fsm.put(State.THIRD, tr);
}
public void activity() { // May be a long process, generating events,
System.err.println(_state);// to opposite to "action()" see below
}
public void handleEvent(Event event) {
Map< Event, State > trs = _fsm.get(_state);
if(trs != null) {
State futur = trs.get(event);
if(futur != null) {
_state = futur;
// here we may call "action()" a small piece of code executed
// once per transition
}
}
}
private final Map<
State, Map<
Event, State >> _fsm = new HashMap<>();
private /* */ State _state = State.FIRST;
}
public class FSM_Test {
public static void main(String[] args) {
Mobile1 m1 = new Mobile1();
m1.activity();
m1.handleEvent(Mobile1.Event.FIRST);
m1.activity();
m1.handleEvent(Mobile1.Event.SECOND);
m1.activity();
m1.handleEvent(Mobile1.Event.FIRST); // Event not handled
m1.activity();
m1.handleEvent(Mobile1.Event.THIRD);
m1.activity();
}
}
输出:
FIRST
SECOND
THIRD
THIRD
FIRST
下面的代码将会给您提供高性能的(10ns的〜/事件)零运行GC状态机实现。只要系统或组件中具有状态概念,就可以使用显式状态机,这不仅使代码更加干净和可扩展,而且可以让人们(甚至程序员)立即看到系统的功能,而无需在众多回调中进行挖掘:
abstract class Machine {
enum State {
ERROR,
INITIAL,
STATE_0,
STATE_1,
STATE_2;
}
enum Event {
EVENT_0,
EVENT_1,
EVENT_2;
}
public static final int[][] fsm;
static {
fsm = new int[State.values().length][];
for (State s: State.values()) {
fsm[s.ordinal()] = new int[Event.values().length];
}
}
protected State state = State.INITIAL;
// child class constructor example
// public Machine() {
// // specify allowed transitions
// fsm[State.INITIAL.ordinal()][Event.EVENT_0.ordinal()] = State.STATE_0.ordinal();
// fsm[State.STATE_0.ordinal()][Event.EVENT_0.ordinal()] = State.STATE_0.ordinal();
// fsm[State.STATE_0.ordinal()][Event.EVENT_1.ordinal()] = State.STATE_1.ordinal();
// fsm[State.STATE_1.ordinal()][Event.EVENT_1.ordinal()] = State.STATE_1.ordinal();
// fsm[State.STATE_1.ordinal()][Event.EVENT_2.ordinal()] = State.STATE_2.ordinal();
// fsm[State.STATE_1.ordinal()][Event.EVENT_0.ordinal()] = State.STATE_0.ordinal();
// fsm[State.STATE_2.ordinal()][Event.EVENT_2.ordinal()] = State.STATE_2.ordinal();
// fsm[State.STATE_2.ordinal()][Event.EVENT_1.ordinal()] = State.STATE_1.ordinal();
// fsm[State.STATE_2.ordinal()][Event.EVENT_0.ordinal()] = State.STATE_0.ordinal();
// }
public final void onEvent(Event event) {
final State next = State.values()[ fsm[state.ordinal()][event.ordinal()] ];
if (next == State.ERROR) throw new RuntimeException("invalid state transition");
if (acceptEvent(event)) {
final State prev = state;
state = next;
handleEvent(prev, event);
}
}
public abstract boolean acceptEvent(Event event);
public abstract void handleEvent(State prev, Event event);
}
如果fsm被大小为S * E的单目数组替代,它也将改善状态机的缓存接近度特性。
有多确定对象创建将成为模拟的瓶颈? – aioobe
我在想enum + switch –
“might”是你问题中的关键字:你创建了更多的对象,但你不希望这样的表现是不可接受的!在分析之前优化是一个坏主意;编码您的理想解决方案,然后优化。 – dasblinkenlight