天天看點

一個超簡單的akka actor例子 一個超簡單的akka actor例子

一個超簡單的akka actor例子

抛開複雜的業務邏輯,讓我們從一個超級簡單的例子學習Akka Actor的用法。 Scala cookbook的作者Alvin Alexander在他的網站上提供了兩個例子。

本文翻譯、整理于他的兩篇文章。

下面幾行代碼就實作了一個actor。

1
      
      
       2
      
      
       3
      
      
       4
      
      
       5
      
      
       6
      
      
       7
      
      
       8
      
      
       9
      
      
       10
      
      
       11
      
      
       12
      
      
       13
      
      
       14
      
      
       15
      
      
       16
      
      
       17
      
      
       18
            
import akka.actor.Actor
      
      
       import akka.actor.ActorSystem
      
      
       import akka.actor.Props
      
      
        
      
      
       class HelloActor extends Actor {
      
      
         def receive = {
      
      
           case "hello" => println("您好!")
      
      
           case _       => println("您是?")
      
      
         }
      
      
       }
      
      
        
      
      
       object Main extends App {
      
      
         val system = ActorSystem("HelloSystem")
      
      
         // 預設的Actor構造函數
      
      
         val helloActor = system.actorOf(Props[HelloActor], name = "helloactor")
      
      
         helloActor ! "hello"
      
      
         helloActor ! "喂"
      
      
       }
            
  • 1到3行是引入必要的類
  • 第5行定義了一個Actor, 實作了receive方法, 如果接收到"hello",傳回一個禮貌性的"您好", 如果接收到其它消息,傳回"您是?"
  • 第12行定義了一個main對象
  • 我們需要一個ActorSystem,是以在第13行建立了一個
  • 第15行建立了一個HellActor的執行個體,傳回結果類型為ActorRef。 這裡HelloActor我們調用預設的構造函數,你也可以調用特定的帶參數的構造函數
  • 第16,17行我們發送了兩個消息給這個actor, actor應該能收到這兩條消息并處理

!

是一個簡化發送消息的操作符, ScalaActorRef為ActorRef定義的一個隐式方法。

1
      
      
       2
      
      
       3
            
trait ScalaActorRef { ref: ActorRef ⇒
      
      
         def !(message: Any)(implicit sender: ActorRef = null): Unit
      
      
       }
            

假定你已經安裝了scala和sbt。建立一個檔案夾,在此檔案夾中建立一個

build.sbt

,内容如下:

1
      
      
       2
      
      
       3
      
      
       4
      
      
       5
            
name := "Hello Test #1" 
      
      
       version := "1.0" 
      
      
       scalaVersion := "2.11.4"
      
      
        
      
      
       libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.3.9"
            

我機器上安裝scala的版本為

2.11.4

,你可以調整為你機器上合适的版本,以及相應的akka的版本。

将上述actor的代碼複制到此檔案夾下的

HelloActor.scala

檔案中。

執行下面的指令:

1
            
C:\akka>sbt run
            

輸出結果

1
      
      
       2
      
      
       3
      
      
       4
      
      
       5
      
      
       6
      
      
       7
      
      
       8
      
      
       9
      
      
       10
      
      
       11
      
      
       12
      
      
       13
      
      
       14
      
      
       15
      
      
       16
      
      
       17
      
      
       18
      
      
       19
      
      
       20
      
      
       21
      
      
       22
            
C:\akka>sbt run
      
      
       [info] Set current project to Hello Test #1 (in build file:/C:/akka/)
      
      
       [info] Updating {file:/C:/akka/}akka...
      
      
       [info] Resolving org.scala-lang#scala-library;2.11.4 ...
      
      
         [info] Resolving com.typesafe.akka#akka-actor_2.11;2.3.9 ...
      
      
         [info] Resolving org.scala-lang#scala-library;2.11.5 ...
      
      
         [info] Resolving com.typesafe#config;1.2.1 ...
      
      
         [info] Resolving org.scala-lang#scala-compiler;2.11.4 ...
      
      
         [info] Resolving org.scala-lang#scala-reflect;2.11.4 ...
      
      
         [info] Resolving org.scala-lang.modules#scala-xml_2.11;1.0.2 ...
      
      
         [info] Resolving org.scala-lang.modules#scala-parser-combinators_2.11;1.0.2 ..
      
      
       .
      
      
         [info] Resolving jline#jline;2.12 ...
      
      
       [info] Done updating.
      
      
       [warn] Scala version was updated by one of library dependencies:
      
      
       [warn]  * org.scala-lang:scala-library:2.11.4 -> 2.11.5
      
      
       [warn] To force scalaVersion, add the following:
      
      
       [warn]  ivyScala := ivyScala.value map { _.copy(overrideScalaVersion = true) }
      
      
       [warn] Run 'evicted' to see detailed eviction warnings
      
      
       [info] Running Main
      
      
       您好!
      
      
       您是?
            

Ctrl

 + 

C

可以終止程式的運作。

這裡還有一個更複雜的例子,涉及到兩個actor的互動。 就像兩個人在乒乒乓乓的打乒乓球。 兩個actor來回的ping pang,直到達到特定的次數才停止。

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
      
      
       32
      
      
       33
      
      
       34
      
      
       35
      
      
       36
      
      
       37
      
      
       38
      
      
       39
      
      
       40
      
      
       41
      
      
       42
      
      
       43
      
      
       44
      
      
       45
            
import akka.actor._
      
      
        
      
      
       case object PingMessage
      
      
       case object PongMessage
      
      
       case object StartMessage
      
      
       case object StopMessage
      
      
        
      
      
       class Ping(pong: ActorRef) extends Actor {
      
      
         var count = 0
      
      
         def incrementAndPrint { count += 1; println("ping") }
      
      
         def receive = {
      
      
           case StartMessage =>
      
      
               incrementAndPrint
      
      
               pong ! PingMessage
      
      
           case PongMessage =>        
      
      
               if (count > 9) {
      
      
                 sender ! StopMessage
      
      
                 println("ping stopped")
      
      
                 context.stop(self)
      
      
               } else {
      
      
       		  incrementAndPrint
      
      
                 sender ! PingMessage
      
      
               }
      
      
         }
      
      
       }
      
      
        
      
      
       class Pong extends Actor {
      
      
         def receive = {
      
      
           case PingMessage =>
      
      
               println("  pong")
      
      
               sender ! PongMessage
      
      
           case StopMessage =>
      
      
               println("pong stopped")
      
      
               context.stop(self)
      
      
       		context.system.shutdown()
      
      
         }
      
      
       }
      
      
        
      
      
       object PingPongTest extends App {
      
      
         val system = ActorSystem("PingPongSystem")
      
      
         val pong = system.actorOf(Props[Pong], name = "pong")
      
      
         val ping = system.actorOf(Props(new Ping(pong)), name = "ping")
      
      
         // start them going
      
      
         ping ! StartMessage
      
      
       }
            

這裡定義了兩個actor: Ping和Pang。

  • Ping 接收StartMessage和 PongMessage。 StartMessage是一個啟動消息,由main對象發送,PongMessage來自Pong actor,如果次數還未達到,它繼續發送PingMessage。
  • Pong 接收StopMessage和 PingMessage。 如果接收到PingMessage,它就發送一個PongMessage, 如果是StopMessage, 停止ActorSystem

這裡調用了Ping的帶參數的構造函數 

Props(new Ping(pong))

參考文檔

  • Simple Scala Akka Actor examples (Hello, world examples)
  • A 'Ping Pong' Scala Akka actors example