簡體   English   中英

在Scala中實現沒有Akka的Actor模型

[英]Implement Actor model without Akka in Scala

我正在做一項小型研究,在沒有Akka的情況下實現Actor,我在Scala中發現了Actor的一種實現。 如何在沒有Akka的情況下實現actor模型?

非常簡單 因為我沒有足夠的聲譽來添加評論,所以我創建了這個問題。 我想知道我是否像下面那樣使用Actor。

1 /如何從主線程關閉該actor?

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)
}

您可以查看scalaz中的Actor model實現並scalaz獲取想法, scalaz actor中的源代碼比akka更容易akka 您可以自由選擇體系結構:您可以像在Akka中一樣使用基於ConcurrentLinkedQueue的郵箱,像在scalaz中一樣將CAS用於AtomicReffernce,如果您使用的是Future機制。 IMO,您必須編寫actor系統的上下文,因此解決問題的第一和第二項是ActorContext的變體:

val contextStack = new ThreadLocal[List[ActorContext]] 

然后關閉,如下所示:

1。

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

2.要存儲父actor和類似任務,必須在其上存儲引用:

def parent: ActorRef

關於每種技術(CAS,郵箱)的優勢很難說,這可能是您研究的變體。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM