2009-10-06 21 views
8

Dopo aver letto sull'uso di react in attori in Scala, ho pensato che lo react condividesse la stessa discussione dato che non c'erano più react in sospeso. Non sembra essere il caso.Quando vengono creati i thread per gli attori di Scala?

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

class SleepyReactor extends Actor { 
    def act() { 
     loop { 
      react { 
       case x => { 
        println("reacting to %s on thread %s".format(x, Thread.currentThread.getName)) 
        Thread.sleep(1000) 
        println("done with " + x) 
       } 
      } 
     } 
    } 
} 
val sleepyOne = new SleepyReactor 
sleepyOne.start 
sleepyOne ! "first" // runs on thread-5 

// wait until completion 

sleepyOne ! "second" // runs on thread-3 

Qualcuno può spiegare perché queste react 's sono in esecuzione su diversi fili e quando un nuovo thread viene creato per un attore con react?

Ho letto da qualche parte react è basato su eventi, e ho preso questo per dire che "reagire attori" condividevano un thread e se uno stava "reagendo" l'altro "reagiva attori" sarebbe stato accodato fino a quando il primo era stato fatto. Ora penso di sbagliarmi. Come funziona e come è diverso da ricevere?

+0

vedi anche http://stackoverflow.com/questions/1251666/scala- attori-ricevere-vs-reagire –

risposta

9

E 'vero che per un attore a base di puro evento, il suo codice viene eseguito reagire sullo stesso thread come messaggio in codice di invio.

Ma in Scala, dal momento che non è desiderabile bloccare un thread quando un attore chiama un'operazione di blocco all'interno del suo codice di reazione e unificare gli attori basati su eventi e thread (essendo in grado di comporli), entrambi i tipi di attori utilizza lo stesso pool di thread ma gli attori basati su thread ottengono i propri thread mentre gli attori basati sugli eventi condividono i thread in base a una coda di attività. Per dettagli, vedere Actors that Unify Threads and Events di Philipp Haller e Martin Odersky

3

La biblioteca scheduler utilizza un pool di thread per controllare l'esecuzione degli attori. Non conosco le specifiche della logica che utilizza, ma, per me, sembrerebbe naturale aspettarsi a:

  • inizializzazione con più di un thread in piscina, come le applicazioni multithread è molto probabile usare più di un thead.

  • Selezionare il thread da utilizzare con un attore in attesa in un modo simile alla coda: i thread vengono liberati alla fine della coda e acquisiti dall'inizio della coda.

Inoltre, presumo che alcuni thread siano utilizzati per gestire la pianificazione stessa e il passaggio di messaggi.

5

Non assumere un thread separato per attore. Il macchinario Scala crea un pool di thread di lavoro e cresce solo se la dimensione degli attori "bloccati" è maggiore della dimensione del pool. Quando il tuo attore chiama receive, si trova in uno stato bloccato finché non riceve il messaggio.

4

per vedere l'effetto descritto nelle risposte precedenti, è necessario generare più di due thread. Questo programma di esempio genera 100 thread con receive e 100 thread con react.

quando lo si esegue, si può vedere che gli attori ricevere ogni occupano un filo, e quelli reagire condividere un piccolo numero di thread. (E 'più facile da vedere quando si ordina l'uscita.)

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

class ReactActor extends Actor { 
    def act { 
    loop { 
     react { 
     case 'Hello => println("React: " + Thread.currentThread) 
     } 
    } 
    } 
} 

class ReceiveActor extends Actor { 
    def act { 
    while (true) { 
     receive { 
     case 'Hello => println("Receive: " + Thread.currentThread) 
     } 
    } 
    } 
} 

object Main { 
    def main(args: Array[String]) { 
    val count = 100 
    val as = new Array[Actor](2 * count) 
    for (i <- 0 until count) { 
     as(i) = new ReactActor 
     as(count + i) = new ReceiveActor 
    } 
    for (a <- as) a.start() 
    actor { 
     println(Thread.currentThread) 
     for (a <- as) a ! 'Hello 
    } 
    } 
} 

L'output ordinato in una tipica esecuzione del programma:

Thread[Thread-102,5,main] 
React: Thread[Thread-102,5,main] 
React: Thread[Thread-102,5,main] 
React: Thread[Thread-102,5,main] 
... 
React: Thread[Thread-102,5,main] 
React: Thread[Thread-103,5,main] 
React: Thread[Thread-103,5,main] 
... 
React: Thread[Thread-103,5,main] 
React: Thread[Thread-104,5,main] 
React: Thread[Thread-104,5,main] 
React: Thread[Thread-104,5,main] 
... 
React: Thread[Thread-104,5,main] 
React: Thread[Thread-105,5,main] 
React: Thread[Thread-105,5,main] 
React: Thread[Thread-105,5,main] 
... 
React: Thread[Thread-105,5,main] 
Receive: Thread[Thread-1,5,main] 
Receive: Thread[Thread-10,5,main] 
Receive: Thread[Thread-100,5,main] 
Receive: Thread[Thread-101,5,main] 
Receive: Thread[Thread-11,5,main] 
Receive: Thread[Thread-12,5,main] 
Receive: Thread[Thread-13,5,main] 
Receive: Thread[Thread-14,5,main] 
Receive: Thread[Thread-15,5,main] 
Receive: Thread[Thread-16,5,main] 
Receive: Thread[Thread-17,5,main] 
Receive: Thread[Thread-18,5,main] 
Receive: Thread[Thread-19,5,main] 
Receive: Thread[Thread-2,5,main] 
Receive: Thread[Thread-20,5,main] 
Receive: Thread[Thread-21,5,main] 
... 
Problemi correlati