我正在寫一個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