유한상태기계(Finite State Machine)

위키백과, 우리 모두의 백과사전.

유한 상태 기계(finite-state machine, FSM) 또는 유한 오토마톤(finite automaton, FA; 복수형: 유한 오토마타 finite automata)는 컴퓨터 프로그램과 전자 논리 회로를 설계하는데에 쓰이는 수학적 모델이다. 간단히 상태 기계라고 부르기도 한다. 유한 상태 기계는 유한한 개수의 상태를 가질 수 있는 오토마타, 즉 추상 기계라고 할 수 있다. 이러한 기계는 한 번에 오로지 하나의 상태만을 가지게 되며, 현재 상태(Current State)란 임의의 주어진 시간의 상태를 칭한다. 이러한 기계는 어떠한 사건(Event)에 의해 한 상태에서 다른 상태로 변화할 수 있으며, 이를 전이(Transition)이라 한다. 특정한 유한 오토마톤은 현재 상태로부터 가능한 전이 상태와, 이러한 전이를 유발하는 조건들의 집합으로서 정의된다.


메시지 처리기도 FSM이 반영된 액터 설계가 가능하며 실제로 이것은

다양한 실시간 메시지를 처리해야하는 액터설계에 중요한 요소로 활용될수 있습니다. 

액터와 별개로 OOP에서 이러한 FSM구현을 구조적으로 하기위해

State Degisn Pattern 이 활용되기도 합니다.

AKKA에서 FSM 유틸리티가 직접적으로 지원도되지만(https://doc.akka.io/docs/akka/2.5/fsm.html)

become(전이)/unbecome(전이상태제거) 등을 활용하여 FSM 설계가 가능해집니다.


HotSwapActor

핫스왑은 작동하는 도중 기능을 바꿀수 있는 기능을 의미하며 , 이것은 유연한 메시지 설계에

도움이 되는 기능중 하나입니다.

  • 현재 감정 상태에따라 다른 반응을 한다.
  • foo 를 받으면 화를 내는 상태가 된다.
  • bar를 받으면 행복한 상태가된다.
  • 감정의 변화가 일어나는 조건을 전이라고 한다.
  • 이미 화난상태이거나 행복한 상태일때 다른 메시지 처리를 한다.



구현샘플

public class HotSwapActor extends AbstractActor {
  private AbstractActor.Receive angry;
  private AbstractActor.Receive happy;

  public HotSwapActor() {
    angry =
      receiveBuilder()
        .matchEquals("foo", s -> {
          getSender().tell("I am already angry?", getSelf());
        })
        .matchEquals("bar", s -> {
          getContext().become(happy);
        })
        .build();

    happy = receiveBuilder()
      .matchEquals("bar", s -> {
        getSender().tell("I am already happy :-)", getSelf());
      })
      .matchEquals("foo", s -> {
        getContext().become(angry);
      })
      .build();
  }
  
  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .matchEquals("foo", s -> 
        getContext().become(angry)
      )
      .matchEquals("bar", s ->
        getContext().become(happy)
      )
      .build();
  }
}

Actor API 의 become(상태변화) 기능으로 구현을 한 샘플이며

HowSwapActor와 같이 이미 구현된 객체를 사용하는것이 아닌, 

유용한 어떠한 액터설계를 우리가 직접 할수있음을 의미합니다. 


SwapperActor

Swapper의 경우 전구와 유사한 상태를 가지는 기능이라고 보면된다

  • 전구는 ON / OFF 두가지 상태를 갖는다.
  • 전구는 반드시 둘중 하나의 상태만 취한다.
  • 각 상태는 특정 조건 (스위치 올림 / 내림 ) 에 따라 변한다
  • 전구를 다음과 같이 정의할 수 있다.
    • ON : 스위치가 올라가면 OFF로 전이
    • OFF : 스위치가 내려가면 ON으로 전이


위와같이 두가지 상태중 하나만 가지는 모델입니다.


구현샘플

public class Swapper extends AbstractLoggingActor {
  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .matchEquals(Swap, s -> {
        log().info("Hi");
        getContext().become(receiveBuilder().
          matchEquals(Swap, x -> {
            log().info("Ho");
            getContext().unbecome(); // resets the latest 'become' (just for fun)
          }).build(), false); // push on top instead of replace
      }).build();
  }
}

public class SwapperApp {
  public static void main(String[] args) {
    ActorSystem system = ActorSystem.create("SwapperSystem");
    ActorRef swapper = system.actorOf(Props.create(Swapper.class), "swapper");
    swapper.tell(Swap, ActorRef.noSender()); // logs Hi
    swapper.tell(Swap, ActorRef.noSender()); // logs Ho
    swapper.tell(Swap, ActorRef.noSender()); // logs Hi
    swapper.tell(Swap, ActorRef.noSender()); // logs Ho
    swapper.tell(Swap, ActorRef.noSender()); // logs Hi
    swapper.tell(Swap, ActorRef.noSender()); // logs Ho
    system.terminate();
  }
}

더복잡한 상태를 가지게될시 AKKA의 FSM 추상화 객체활용이 가능하며

상태의 저장까지 책임지는 영속성 Part에서도 FSM의 기능은 유용합니다.

참고 :