2013-02-10 36 views
0

我完全不熟悉這一點,但這裏是一個Scala演員,它是用我的課程創建的,只能爲其他演員生成消息。我希望它每秒醒來,收集一些指標,將它們運送給其他演員,然後再回去睡覺。當終止應用程序,我需要發送此演員一條消息,以退出正確的方法來終止Scala演員只生成消息

class Node() { 
    println("A new Node is being constructed") 
    val load_monitor: Actor = actor { 
    val s: Sigar = new Sigar 
    while (true) { 
     Thread.sleep(1000); 

     // Will be replaced with something like 
     // load_manager | s.getCpuSystem 
     println(s.getCpuPerc) 

     self.receiveWithin(100) { 
     case "EXIT" => exit() 
     case TIMEOUT => {} 
     } 
    } 
    } 

    // Other Node code below... 
} 

這似乎工作,但我沒有信心它是正確的。調用Thread.sleep是否聰明?如果這是一個完整的線程,我現在有一個睡眠線程。如果這是一個事件,我現在是否阻止了一些事件處理隊列?我可以使用接收/反應的東西來更正確地做到這一點嗎?我無法理解接收/反應是否有效地阻止了actor的執行,這意味着我無法每秒醒來檢查指標。我也考慮過下面的代碼,但我不知道它是否比上面的代碼更好!

class Node() { 
    println("A new Node is being constructed") 
    val load_monitor: Actor = actor { 
    val s: Sigar = new Sigar 
    while (true) { 
     self.receiveWithin(1000) { 
     case "EXIT" => exit() 
     // Will be replaced with something like 
     // load_manager | s.getCpuSystem 
     case TIMEOUT => println(s.getCpuPerc) 
     } 
    } 
    } 

    // Other Node code below... 
} 
+0

我不確定這個答案,因爲我對Scala Actor不熟悉,但是我建議查看Akka(http://akka.io/),對於所有的意圖和目的,都將Scala Actors替換爲斯卡拉2.10。 – adelbertc 2013-02-10 05:43:28

+0

我一定在研究它,但我的問題在於尋找對如何使用Actor範例的理解,所以我不認爲切換實現在這一點上會有很大的幫助。誠然,我知道什麼:-)如果Akka建立在scala演員之上,我仍然有點困惑,他們的常見問題在「什麼是akka」問題上很空白 – Hamy 2013-02-10 05:53:13

+1

不,akka是一個完全獨立的實現,超出了斯卡拉演員的能力。 – drexin 2013-02-10 08:12:50

回答

3

首先,我強烈推薦使用Akka,這些對於所有的意圖和目的都取代了從Scala 2.10開始的Scala Actor。 Akka是Actor範例的獨立實現,並不基於Scala Actor。這就是說,我將基於Akka 2.x的答案,因爲我最熟悉Akka 2。x,因爲它可能證明對你更有用,因爲Akka現在是Scala的事實上的Actor實現(也可能是整個JVM)。

Actor範例很容易理解 - 它基於兩個主要思想:封裝的可變性和消息傳遞。每個Actor封裝它自己的狀態,除了Actor本身之外,其他任何內容都不應觸及Actor的內部狀態。參與者通過消息進行通信。如果一些演員A想要改變封裝在演員B內部的變量(例如A代表客戶端,而B代表客戶端的銀行賬戶),則A將發送一條消息給B,表明這樣 - 請注意B可以忽略該消息。

參與者在任何時候都不會綁定線程,他們只有在郵件在郵箱中等待郵件時纔會「醒來」。因此,撥打Thread.sleep不僅是不必要的,但不建議。

在Akka中,消息是寬鬆輸入的(Any),因此您通常希望以case類的形式發送消息(不僅易於構建,而且還可以模式匹配,對於Akka中的receive有用演員)。

您可以爲每個將每x秒發送一條消息的每個Actor創建一個調度程序(Akka具有使這非常簡單的工具)。此消息將觸發Actor醒來,閱讀郵箱中的郵件(這可能是指示應收集統計信息的消息),並對其執行操作。

要將消息廣播給其他幾個Actor,有很多方法可以做到這一點。一種簡單的方法是在度量收集Actor中保留某種ActorRef(特定於Akka)的集合,並且每次Actor醒來收集統計信息時,它只會向與該集合對應的每個Actor發送一條消息。還有很多其他的方法可以做到這一點。

如果你真的對在Scala(或通用JVM)中使用Actors感興趣,我強烈推薦Derek Wyatt的書Akka Concurrency

+0

根據Derek Wyatt的書推薦。 – 2013-02-10 15:28:59

1

我完全新的這個

在這種情況下,作爲adelbertc說,你真的應該用阿卡演員開始,除非你被卡住規定使用Scala的演員來維持一個遺留應用程序(因爲Scala演員在當前的Scala版本中被棄用,並且會在下一個版本中被刪除)。

調用Thread.sleep是否智能?如果這是一個完整的線程,我現在有一個睡眠線程。

沒有,如果你打電話Thread.sleep總是有一個沉睡的線程。參與者不會以某種方式改變現有方法的含義!

您的第二個選項更好,但​​表示此演員將在其自己的線程中運行,更好地使用reactWithin並參見this answer。你可以使用Scheduler

2

在演員中使用while(true)Thread.sleep不是一個好主意。你不想阻止。我會定期向演員發送一條消息,然後對消息作出反應。

例如:

import scala.actors.Actor 

import java.util.Timer 
import java.util.TimerTask 

case object DoSomething 

class MyActor extends Actor { 
    def act() { 
    loop { 
     react { 
     case DoSomething => 
      // do measurement 
      println(Runtime.getRuntime.freeMemory + " bytes free") 

     case 'kill => 
      exit() 
     } 
    } 
    } 
} 

val actor = new MyActor 
actor.start 

val timer = new Timer(true) 

timer.schedule(new TimerTask { 
    def run { 
    actor ! DoSomething 
    } 
}, 1000, 1000) 

我也建議你使用阿卡代替。隨着阿卡同樣的事情應該是這樣的(未測試):

import akka.actor._ 
import scala.concurrent.duration._ 

case object DoSomething 

class MyActor extends Actor { 

    context.scheduler.schedule(1 second, 1 second) { 
    self ! DoSomething 
    } 

    def receive = { 
    case DoSomething => 
     // do measurement 
     println(Runtime.getRuntime.freeMemory + " bytes free") 
    } 
} 

val system = new ActorSystem("MySystem") 

system.actorOf(Props[MyActor]) 

要殺死一個阿卡演員可以隨時向它發送akka.actor.PoisonPill,隊列中的所有剩餘的消息已經被處理後,這會殺了演員。