2014-08-29 3 views
1

enum 기반 상태 시스템이 있습니다. 다음은 내 상태의 구조와 내가 가진 문제점을 설명하는 예제 코드입니다.enum 기반 Finite State Machine에서 경쟁 조건 피하기

public enum LinkStates implements StuffDoneListener { 

    ... 

    DO_SOME_WORK { 
     public void process() { 
      .... 
      .... 
      someObject.startDoingSpecialStuff(); 
      outerClass.toState(WAIT_FOR_EVENT); 
     } 
    }, 


    WAIT_FOR_EVENT { 
     public void process() { 
      // does nothing 
     } 

     public void onSpecialStuffComplete() { 

     } 
    } 

    ... 

    // Default implementation of interface methods which individual states 
    // may override at will 
    public void onSpecialStuffComplete() { 
    } 

} 

process() 방법은 상태가 변경 될 때 호출되는 것입니다. 각 주에서는 다양한 이벤트를 수신하기 위해 다양한 청취자 메소드를 재정의하는 경향이 있습니다.

상태 DO_SOME_WORK은 오랜 시간 작업을 수행하기 위해 개체에서 메서드 (startDoingSpecialStuff())를 호출합니다. 이 객체는 UI가 아닌 또 다른 객체 인 Thread에서 작업을 수행합니다. 작업이 완료되면 상태 머신은 onSpecialStuffComplete()을 통해 통지를받습니다.이 상태 머신은 작업을 호출 한 원래 스레드에서 호출됩니다. 여기에서 분명한 문제는 작업이 빨리 완료되면 청취자 콜백이 실행 된 후 FSM이 WAIT_FOR_EVENT으로 이동한다는 경쟁 조건이있을 수 있다는 것입니다.

그것은 거기에서 통보 들어가면 그것이 WAIT_FOR_EVENT에가는 귀찮게하지 알 수 있도록 또한, DO_SOME_WORK에서 onSpecialStuffComplete()를 재정 의하여 아마이 '수정'에 나를 위해 매우 간단하다. 또는 어느 정도 조잡한 boolean 플래그를 사용하여 해당 상태로 이동하자마자 WAIT_FOR_EVENT이 해당 이벤트가 이미 시작되었는지 확인하기 위해 폴링 할 수 있습니다.

그러나 내가 찾고있는 것은이 일반적인 문제에 대한보다 우아하고 견고한 해결책입니다.

나는 Android 태그를 사용했는데 이것은 일반적인 Java 디자인 패턴 질문으로 간주 될 수 있습니다. 안드로이드 전용 클래스에 의존하는 더 나은 해결책이있는 경우를 대비하여.

+0

"UI"스레드 ("onSpecialStuffComplete"와 동일한 스레드)에서 DO_SOME_WORK.process가 호출 되었습니까? 그렇다면 경쟁 조건이 보이지 않습니다. 그렇지 않다면 DO_SOME_WORK.process가 호출 순서를 역순으로 할 수 없기 때문에 specialStuff이 시작되기 전에 outerClass가 WAIT_FOR_EVENT가됩니다. – Sbodd

답변

1

DO_SOME_WORKWAIT_FOR_EVENT은 병합 할 수 있습니다. 상태 전환은 "특별한 물건"이 완료 될 때까지 발생하지 않습니다이 이런 식으로 기록 될 때

public enum LinkStates implements StuffDoneListener { 
    // ... 

    START_SOME_WORK_AND_WAIT { 
     public void process() { 
      // .... 
      someObject.startDoingSpecialStuff(); 
     } 

     public void onSpecialStuffComplete() { 
      outerClass.toState(EVENT_IS_COMPLETE); 
     } 
    }, 

    EVENT_IS_COMPLETE { 
     public void process() { 
      // ... 
     } 
     // ... 
    } 

    // ... 

    public void onSpecialStuffComplete() { 
    } 
} 

나는 그래서이 게시되지 않은 뭔가를 아프게하지 않는 가정, 경쟁 조건이 표시되지 않습니다, 그것은 잘 작동해야합니다.

+0

많은 감사. 실제 코드는 훨씬 더 복잡하지만 생각을하고 개념적으로 나는 지금 이와 비슷한 것을 가지고 있습니다. 여기에서 배운 요점은 상태 선택에주의해야하며 이벤트를 트리거하고 한 국가 내에서 후속 콜백을 받음으로써 경쟁 조건을 없애는 것입니다. – Trevor