Czy aktorzy Scali mogą przetwarzać wiele wiadomości jednocześnie?

Odpowiedź na moje ostatnie pytanie wskazywała, że aktor przetwarzał swoje wiadomości pojedynczo . Czy to prawda? Nie widzę nic, co wyraźnie mówi, że (w Programowanie w Scali), który zawiera następujący fragment (S. 593)

Jeśli [metoda react] znajdzie wiadomość, którą można obsłużyć, [ona] zaplanuje obsługę tej wiadomości do późniejszego wykonania i wyrzuci wyjątek

(akcent mój własny). Dwa powiązane pytania:

  1. zakładając, że aktor może przetwarzać wiele wiadomości w sposób symulowany, Jak mogę zmusić aktora do przetwarzania wiadomości 1 na raz (jeśli to jest to, co chcę zrobić)? (używając receive?)
  2. W związku z tym, że nie jest to możliwe, nie jest to możliwe, ponieważ nie jest to możliwe, ponieważ nie jest to możliwe, ponieważ nie jest to możliwe.]}

edit: trochę testowania zdaje się świadczyć o tym, że się mylę i że aktorzy rzeczywiście sekwencyjny. Więc to pytanie # 2, na które muszę odpowiedzieć

Author: Community, 2009-06-17

3 answers

Aktorzy przetwarzają jedną wiadomość na raz. Klasyczny wzorzec przetwarzania wielu wiadomości polega na tym, aby jeden koordynator był frontowy dla puli podmiotów konsumenckich. Jeśli używasz Reacta, Pula odbiorców może być duża, ale nadal będzie używać tylko niewielkiej liczby wątków JVM. Oto przykład, w którym tworzę pulę 10 konsumentów i jednego koordynatora do ich front.

import scala.actors.Actor
import scala.actors.Actor._

case class Request(sender : Actor, payload : String)
case class Ready(sender : Actor)
case class Result(result : String)
case object Stop

def consumer(n : Int) = actor {
  loop {
    react {
      case Ready(sender) => 
        sender ! Ready(self)
      case Request(sender, payload) =>
        println("request to consumer " + n + " with " + payload)
        // some silly computation so the process takes awhile
        val result = ((payload + payload + payload) map {case '0' => 'X'; case '1' => "-"; case c => c}).mkString
        sender ! Result(result)
        println("consumer " + n + " is done processing " + result )
      case Stop => exit
    }
  }
}

// a pool of 10 consumers
val consumers = for (n <- 0 to 10) yield consumer(n)

val coordinator = actor {
  loop {
     react {
        case msg @ Request(sender, payload) =>
           consumers foreach {_ ! Ready(self)}
           react {
              // send the request to the first available consumer
              case Ready(consumer) => consumer ! msg
           }
         case Stop => 
           consumers foreach {_ ! Stop} 
           exit
     }
  }
}

// a little test loop - note that it's not doing anything with the results or telling the coordinator to stop
for (i <- 0 to 1000) coordinator ! Request(self, i.toString)

Ten kod sprawdza, który konsument jest dostępny i wysyła żądanie do tego konsumenta. Alternatywami są wystarczy losowo przypisać do konsumentów lub użyć round robin scheduler.

W zależności od tego, co robisz, możesz być lepiej obsługiwany z przyszłości Scali. Na przykład, jeśli naprawdę nie potrzebujesz aktorów, wszystkie powyższe maszyny mogą być napisane jako

import scala.actors.Futures._

def transform(payload : String) = {      
  val result = ((payload + payload + payload) map {case '0' => 'X'; case '1' => "-"; case c => c}).mkString
  println("transformed " + payload + " to " + result )
  result
}

val results = for (i <- 0 to 1000) yield future(transform(i.toString))
 26
Author: James Iry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-17 17:41:26

Myślę, że odpowiedź jest taka, że an Actor nie może obsługiwać wiadomości aynchronicznie. Jeśli masz Actor, który powinien nasłuchiwać wiadomości, w których te wiadomości mogą być obsługiwane asynchronicznie , to może być napisane tak:

val actor_ = actor {

  loop {
    react {
      case msg =>
        //create a new actor to execute the work. The framework can then 
        //manage the resources effectively
        actor {
          //do work here
        }
      }
    }
  }
 6
Author: oxbow_lakes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-17 14:13:53

Jeśli chcesz robić wiele rzeczy, powinieneś używać wielu aktorów. Powodem wykorzystania aktorów jest podział pracy na wiele niezależnych procesów.

 0
Author: mamboking,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-17 13:39:19