blocking
funge da suggerimento per ExecutionContext
che contiene codice di blocco, in modo che possa generare un nuovo thread per evitare deadlock. Ciò presuppone che lo ExecutionContext
possa farlo, ma non tutti sono fatti per.
Diamo un'occhiata a ciascuno uno per uno.
Future(blocking(blockingCall()))
Questo richiede un implicito ExecutionContext
per eseguire il Future
. Se lo ExecutionContext
utilizzato è un BlockContext
(come scala.concurrent.ExecutionContext.Implicits.global
), potrebbe essere in grado di generare un nuovo thread nel suo pool di thread per gestire la chiamata di blocco, se necessario. Se non lo è, allora non succede nulla di speciale.
blocking(Future(blockingCall()))
Questo ci dice che Future(blockingCall())
può essere una chiamata di blocco, quindi viene trattato lo stesso come sopra. Tranne che qui, Future.apply
non è bloccante, quindi l'uso di blocking
non fa altro che aggiungere un po 'di overhead. Non importa che cosa lo chiamiamo ExecutionContext
da qui, in quanto non blocca comunque. Tuttavia , la chiamata di blocco all'interno il Future
bloccherà un filo nella ExecutionContext
cui sta girando, senza il suggerimento che il suo bloccaggio. Quindi, non c'è motivo di farlo mai.
Ho spiegato blocking
in profondità in this answer.
Esempi REPL:
import java.util.concurrent.Executors
import scala.concurrent._
val ec = scala.concurrent.ExecutionContext.Implicits.global
val executorService = Executors.newFixedThreadPool(4)
val ec2 = ExecutionContext.fromExecutorService(executorService)
def blockingCall(i: Int): Unit = { Thread.sleep(1000); println("blocking call.. " + i) }
// Spawns enough new threads in `ec` to handle the 100 blocking calls
(0 to 100) foreach { i => Future(blocking(blockingCall(i)))(ec) }
// Does not spawn new threads, and `ec2` reaches thread starvation
// execution will be staggered as threads are freed
(0 to 100) foreach { i => Future(blocking(blockingCall(i)))(ec2) }
// `blocking` does nothing because the `Future` is executed in a different context,
// and `ec2` reaches thread starvation
(0 to 100) foreach { i => blocking(Future(blockingCall(i))(ec2)) }
// `blocking` still does nothing, but `ec` does not know to spawn new threads (even though it could)
// so we reach thread starvation again
(0 to 100) foreach { i => blocking(Future(blockingCall(i))(ec)) }
fonte
2015-06-24 15:16:05
Non è anche una parola chiave, è solo un metodo. –
Questa è stata una grande spiegazione! Grazie mille! – Manu