2016-10-21 3 views
0

나는 액카가없는 액터를 구현하는 저의 작은 연구를하고 있습니다 스칼라에서 액터의 구현을 하나 발견했습니다. (How to implement actor model without Akka?)스칼라에서 Akka가없는 액터 모델 구현

매우 간단합니다. 코멘트를 추가할만한 평판이 없기 때문에이 질문을 만듭니다. 아래처럼 Actor를 사용하고 있는지 궁금합니다.

1/어떻게 그 액터를 메인 스레드에서 종료 할 수 있습니까?

2/어떻게 부모 배우처럼 Akka와 유사한 기능을 추가하고 요청을 죽이고 방법이 될 수 있습니까?

import scala.concurrent._ 

trait Actor[T] { 
     implicit val context = ExecutionContext.fromExecutor(java.util.concurrent.Executors.newFixedThreadPool(1)) 
     def receive: T => Unit 
     def !(m: T) = Future { receive(m) } 
} 

import scala.concurrent._ 

/** 
    * Created by hminle on 10/21/2016. 
    */ 
trait Message 
case class HelloMessage(hello: String) extends Message 
case class GoodByeMessage(goodBye: String) extends Message 

object State extends Enumeration { 
    type State = Value 
    val Waiting, Running, Terminating = Value 
} 

trait Actor[T] { 
    implicit val context = ExecutionContext.fromExecutor(java.util.concurrent.Executors.newFixedThreadPool(1)) 
    private var state: State.State = State.Waiting 
    def handleMessage: T => Unit ={ 
    if(state == State.Waiting) handleMessageWhenWaiting 
    else if(state == State.Running) handleMessageWhenRunning 
    else handleMessageWhenTerminating 
    } 
    def !(m: T) = Future {handleMessage(m)} 
    def handleMessageWhenWaiting: T => Unit 
    def handleMessageWhenRunning: T => Unit 
    def handleMessageWhenTerminating: T => Unit 
    def transitionTo(destinationState: State.State): Unit = { 
    this.state = destinationState 
    } 
} 

class Component1 extends Actor[Message]{ 
    def handleMessageWhenRunning = { 
    case HelloMessage(hello) => { 
     println(Thread.currentThread().getName + hello) 
    } 
    case GoodByeMessage(goodBye) => { 
     println(Thread.currentThread().getName + goodBye) 
     transitionTo(State.Terminating) 
    } 
    } 

    def handleMessageWhenWaiting = { 
    case m => { 
     println(Thread.currentThread().getName + " I am waiting, I am not ready to run") 
     transitionTo(State.Running) 
    } 
    } 

    def handleMessageWhenTerminating = { 
    case m => { 
     println(Thread.currentThread().getName + " I am terminating, I cannot handle any message") 
     //need to shutdown here 
    } 
    } 

} 
class Component2(component1: Actor[Message]) extends Actor[Message]{ 
    def handleMessageWhenRunning = { 
    case HelloMessage(hello) => { 
     println(Thread.currentThread().getName + hello) 
     component1 ! HelloMessage("hello 1") 
    } 
    case GoodByeMessage(goodBye) => { 
     println(Thread.currentThread().getName + goodBye) 
     component1 ! GoodByeMessage("goodbye 1") 
     transitionTo(State.Terminating) 
    } 
    } 

    def handleMessageWhenWaiting = { 
    case m => { 
     println(Thread.currentThread().getName + " I am waiting, I am not ready to run") 
     transitionTo(State.Running) 
    } 
    } 

    def handleMessageWhenTerminating = { 
    case m => { 
     println(Thread.currentThread().getName + " I am terminating, I cannot handle any message") 
     //need to shutdown here 
    } 
    } 
} 
object ActorExample extends App { 
    val a = new Component1 
    val b = new Component2(a) 
    b ! HelloMessage("hello World 2") 
    b ! HelloMessage("hello World 2, 2nd") 
    b ! GoodByeMessage("Good bye 2") 
    println(Thread.currentThread().getName) 
} 

답변

0

당신은 scalazActor model 구현을보고 그것에서 아이디어를 취할 수 위의 코드를 적응하기 위해 노력하고 내 자신의 예입니다, scalaz actor의 소스 코드를보다 통찰력을위한 쉽습니다 akka. 아키텍처에 대한 선택의 자유가 있습니다. Akka와 같은 ConcurrentLinkedQueue를 기반으로 사서함을 사용할 수 있고, scalaz와 같이 AtomicReffernce에 CAS를 사용할 수 있습니다. 미래의 메커니즘을 사용할 수 있습니다. IMO, 당신은 당신의 배우 시스템의 문맥을 쓰기 때문에이 ActorContext의 변형의 질문에 제 1 및 제 2 항목을 해결해야합니다

val contextStack = new ThreadLocal[List[ActorContext]] 

및 종료는 다음과 같이 할 수 있습니다

1.

case Kill      ⇒ throw new ActorKilledException("Kill") 
case PoisonPill     ⇒ self.stop() 

2. 부모 배우와 유사한 작업을 저장, 당신은 그들에 대한 참조를 저장해야합니다

def parent: ActorRef 

모든 기술 (CAS, 우편함)의 이점에 대해 말하기는 어렵습니다. 연구에있어 가능한 변형입니다.