0

私はこれにまったく慣れていませんが、これは私のクラスで作成され、他のアクターへのメッセージを生成するためだけに生きている 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 の呼び出しはスマートですか? これが完全なスレッドである場合、スリープ状態のスレッドがあります。これがイベントの場合、イベント処理キューをブロックしましたか? これをより適切に行うために、受信/反応のものを使用できますか? receive/react がアクターの実行を効果的に停止するかどうかを理解するのに苦労しています。つまり、メトリックをチェックするために毎秒目を覚ますことができませんでした。次のコードも検討しましたが、上記のコードよりも優れているかどうかはわかりません!

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...
}
4

3 に答える 3

3

まず最初に、Scala 2.10 で Scala Actors に取って代わったAkkaを使用することを強くお勧めします。Akka は Actor パラダイムの独立した実装であり、Scala アクターに基づいていません。

そうは言っても、私は Akka 2.x に最も精通しており、Akka が事実上のアクターであるため、Akka 2.x がより役立つ可能性があるため、Akka 2.x に基づいて回答します。 Scala (およびおそらく JVM 全体) の実装。

アクター パラダイムは簡単に理解できます。カプセル化された可変性とメッセージ パッシングという 2 つの主要なアイデアに基づいています。各アクタは自身の状態をカプセル化します。アクタ自体以外に、アクタの内部状態に影響を与えるものは何もありません。アクターはメッセージを介して通信します。アクター A がアクター B 内にカプセル化された変数を変更したい場合 (たとえば、A がクライアントを表し、B がクライアントの銀行口座を表している場合など)、A は B にそのことを示すメッセージを送信します。B はメッセージを自由に無視できることに注意してください。

アクターは常にスレッドを結び付けているわけではなく、メッセージがメールボックスで待機しているときにのみ「ウェイクアップ」します。したがって、への呼び出しThread.sleepは不要であるだけでなく、推奨されません。

Akka では、メッセージは緩く型付けされているため ( )、通常はケース クラスの形式でメッセージを送信する必要があります (これは、構築が簡単であるだけでなく、Akka ActorAnyでのパターン マッチにも役立ちます)。receive

アクターごとに x 秒ごとにメッセージを送信するスケジューラを作成できます (Akka には、これを非常に簡単にするためのツールがあります)。このメッセージは、Actor を起動させ、メールボックス内のメッセージを読み取り (これはおそらく、統計を収集する必要があることを示すメッセージです)、それに基づいて行動します。

メッセージを他のいくつかのアクターにブロードキャストするには、さまざまな方法があります。簡単な方法の 1 つは、(Akka 固有の) の何らかのコレクションをActorRefメトリクス収集アクターに保持することです。アクターが起動して統計を収集するたびActorに、そのコレクションに対応するすべての人にメッセージを送信するだけです。これを行う方法は他にもたくさんあります。

Scala (または一般的な JVM) でのアクターの使用に本当に興味がある場合は、Derek Wyatt の著書Akka Concurrencyを強くお勧めします。

于 2013-02-10T08:44:19.313 に答える
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)

また、代わりにakkaを使用することをお勧めします。akkaを使用すると、同じことが次のようになります(テストされていません)。

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アクターを強制akka.actor.PoisonPill終了するには、いつでも送信できます。これにより、キューに残っているすべてのメッセージが処理された後、アクターが強制終了されます。

于 2013-02-10T08:27:33.253 に答える
1

私はこれに完全に新しいです

この場合、adelbertcが言うように、レガシーアプリケーションを維持するためにScalaアクターを使用するという要件に固執しない限り、実際にはAkkaアクターから始める必要があります(Scalaアクターは現在のScalaバージョンでは非推奨であり、次のバージョンで削除されるため) 。

Thread.sleepの呼び出しは賢いですか?これがフルスレッドの場合、スリープスレッドがあります。

いいえ、電話をかけるThread.sleep常に眠っているスレッドがあります。アクターは、既存のメソッドの意味を何とか変更しません!

2番目のオプションの方がreceiveWithin優れていますが、このアクターは独自のスレッドで実行されるため、この回答reactWithinをより適切に使用して確認できます。

Akkaアクターを使用すると、スケジューラーを使用できます。

于 2013-02-10T08:27:23.850 に答える