일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 블록체인
- Golang
- 하이브리드앱
- play2 강좌
- 플레이프레임워크
- 이더리움
- Play2 로 웹 개발
- Hyperledger fabric gossip protocol
- Adapter 패턴
- Akka
- 파이썬 머신러닝
- 안드로이드 웹뷰
- hyperledger fabric
- 파이썬 데이터분석
- 엔터프라이즈 블록체인
- 하이퍼레저 패브릭
- CORDA
- 스칼라 동시성
- 그라파나
- 파이썬 동시성
- 파이썬
- 스칼라
- Actor
- play 강좌
- Play2
- 스위프트
- 스칼라 강좌
- 파이썬 강좌
- akka 강좌
- 주키퍼
- Today
- Total
HAMA 블로그
예제로 보는 아카(akka) - 7. 상태머신 ( 상태에 따른 행동변화 ) 본문
- Scala 2.11 기반
- Akka 2.4.11 기반
- Learning Concurrent Programming in Scala 참고
상태머신 (상태에 따른 행동변화 )
- 액터가 자신의 상태를 바꿈에 따라 메세지를 처리하는 방식도 달라 진다.
- 아카 액터에서 receive 메소드 안에 상태에 따른 여러 행위를 넣는것은 바람직 하지 않다.
class CountdownActor extends Actor {
var n = 10
def receive = if (n > 0 ) { case "count" => ...do somthing .. n -=1} else PartialFunction.empty
}
- n 이 0 보다 클 경우에는 어떤 행동을 하고
- n 이 0 일때는 아무것도 안한다.
- receive 함수를 보면 if 문을 통해 부분함수가 다르게 반환된다. 이렇게 하면 안된다.!!
상태에 따른 행위를 애초에 나누어서 처리 해야하는데, 그때 become 이 사용된다. 코드를 살펴보자.
become
class CountdownActor extends Actor {
var n = 10
def counting: Actor.Receive = {
case "count" =>
n -= 1
log(s"n = $n")
if (n == 0) context.become(done)
}
def done = PartialFunction.empty
def receive = counting
}
- 초기 receive 메소드에 counting 이라는 메소드를 지정했다. 즉 초기 상태에 매핑되는 메소드가 counting
- 액터의 상태가 n=0 으로 바뀌면 context.become(done) 을 이용해서 매핑되는 메소드도 done으로 바꿈.
class DictionaryActor extends Actor {
private val log = Logging(context.system, this)
private val dictionary = mutable.Set[String]()
def receive = uninitialized
def uninitialized: PartialFunction[Any, Unit] = {
case DictionaryActor.Init(path) =>
val stream = getClass.getResourceAsStream(path)
val words = Source.fromInputStream(stream)
for (w <- words.getLines) dictionary += w
context.become(initialized)
}
def initialized: PartialFunction[Any, Unit] = {
case DictionaryActor.IsWord(w) =>
log.info(s"word '$w' exists: ${dictionary(w)}")
case DictionaryActor.End =>
dictionary.clear()
context.become(uninitialized)
}
override def unhandled(msg: Any) = {
log.info(s"message $msg should not be sent in this state.")
}
}
object DictionaryActor {
case class Init(path: String)
case class IsWord(w: String)
case object End
}
object ActorsBecome extends App {
val dict = ourSystem.actorOf(Props[DictionaryActor], "dictionary")
dict ! DictionaryActor.IsWord("program")
Thread.sleep(1000)
dict ! DictionaryActor.Init("/org/learningconcurrency/words.txt")
Thread.sleep(1000)
dict ! DictionaryActor.IsWord("program")
Thread.sleep(1000)
dict ! DictionaryActor.IsWord("balaban")
Thread.sleep(1000)
dict ! DictionaryActor.End
Thread.sleep(1000)
dict ! DictionaryActor.IsWord("termination")
Thread.sleep(1000)
ourSystem.shutdown()
}
- uninitialized 로 초기상태 에서 Init 가 호출되어 초기화가 완료되면 initialized 로 상태를 바꿈.
- initialized 상태 에서는 IsWord 메세지를 받아서 작업을 함. 작업 끝을 알리는 메세지를 받으면 uninitialized 로 행동을 다시바꿈.
'Akka' 카테고리의 다른 글
예제로 보는 아카(akka) - 9. akka I/O (TCP 통신) (0) | 2016.10.07 |
---|---|
예제로 보는 아카(akka) - 8. 원격 액터 (0) | 2016.10.07 |
예제로 보는 아카(akka) - 6. 액터 관리 (고장/예외 처리하기) (0) | 2016.10.05 |
예제로 보는 아카(akka) - 5. 액터 사이의 통신및 액터 멈추기 (0) | 2016.10.05 |
예제로 보는 아카(akka) - 4. 액터 생명 주기 (0) | 2016.10.05 |