Scala 【15 Actor 入門 】

Actor

​ Scala 的 Actor 類似於 Java 中的多線程編程。但是不同的是,Scala 的 Actor提供的模型與多線程有所不同。Scala 的 Actor 儘可能地避免鎖和共享狀態,從而避免多線程併發時出現資源爭用的情況,進而提升多線程編程的性能。此外, Scala Actor 的這種模型還可以避免死鎖等一系列傳統多線程編程的問題。

​ Spark 中使用的分佈式多線程框架,是Akka 。Akka 也實現了類似 Scala Actor的模型,其核心概念同樣也是 Actor。

Actor的創建、啓動和消息收發

​ Scala 提供了 Actor trait 來讓我們更方便地進行 actor 多線程編程,Actor trait 就類似於 Java 中的 Thread 和 Runnable 一樣,是基礎的多線程基類和接口。我們只要重寫 Actor trait 的 act 方法,即可實現自己的線程執行體,與 Java 中重寫 run 方法類似。

​ 此外,使用 start() 方法啓動 actor;使用 ! 符號向 actor 發送消息;actor 內部使用 receive 和模式匹配接收消息。

import scala.actors.Actor

class HelloActor extends Actor{
    def act(){
        while(true){
            receive{
                case name:String => println("Hello," + name)
            }
        }
    }
}

val helloActor = new HelloActor

helloActor.start()

helloActor ! "Li"
收發 case class 類型的消息

​ Scala 的 Actor 模型與 Java 的多線程模型之間,很大的一個區別就是,Scala Actor 天然支持線程之間的精準通信;即一個 actor 可以給其他 actor 直接發送消息。這個功能是非常強大和方便的。

​ 要給一個 actor 發送消息,需要使用 “actor ! 消息” 的語法。在 Scala 中,通常建議使用樣例類,即 case class 來作爲消息進行發送。然後在 actor 接收消息之後,可以使用 Scala 強大的模式匹配功能來進行不同消息的處理。

case class Login(username:String, password:String)

case class Register(username:String, password:String)

class UserManageActor extends Actor{
    def act(){
        while(true){
            receive{
                case Login(username,password) => println("login,username is " + username + ",password is " + password)
                case Register(username,password) => println("register,username is " + username + ",password is " + password)
            }
        }
    }
}

val userManageActor = new UserManageActor

userManageActor.start()

userManageActor ! Register("Li","123")

userManageActor ! Login("Li","123")

Actor之間互相收發消息

​ 如果兩個 Actor 之間要互相收發消息,那麼 Scala 的建議是,一個 actor 向另外一個 actor 發送消息時,同時帶上自己的引用;其他 actor 收到自己的消息時,直接通過發送消息的 actor 的引用,即可以給它回覆消息。

case class Message(content:String, sender:Actor)

class LiTelephoneActor extends Actor{
    def act(){
        while(true){
            receive{
                case Message(Content,sender) => {
                    println("Li telephone: " + content);
                    sender ! "I'm li, pleace call me after 10 minutes."
                }
            }
        }
    }
}

class ChyTelephoneActor(val LiTelephoneActor:Actor) extends Actor{
    def act(){
        LiTelephoneActor ! Message("Hello,Li, I'm Chy", this)
        receive{
            case response:String => println("Chy telephone: " + response)
        }
    }
}
同步消息和Future

​ 默認情況下,消息都是異步的;但是如果希望發送的消息是同步的,即對方接受後,一定要給自己返回結果,那麼可以使用 !? 的方式發送消息。

val reply = actor !? message

​ 如果要異步發送一個消息,但是在後續要獲得消息的返回值,那麼可以使用 Future,即 !! 語法。

val future = actor !! message
val reply = future()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章