2013-05-03 4 views
13

sto cercando di capire i futures Scala proveniente da Java sfondo: Capisco si può scrivere:Scala - futures e concorrenza

val f = Future { ... } 

poi ho due domande:

  1. Come è questo futuro programma ? Automaticamente?
  2. Quale utilità di pianificazione utilizzerà? In Java si utilizza un executor che potrebbe essere un pool di thread, ecc.

Inoltre, come è possibile ottenere un scheduledFuture, quello che viene eseguito dopo un intervallo di tempo specifico? Grazie

+1

Se si desidera controllare direttamente quando un futuro sarà soddisfatto, è necessario utilizzare una promessa. –

+1

Le promesse sono un po 'diverse: sono essenzialmente un 'Futuro' vista dal punto di vista dell'esecutore (cioè un contenitore in scrittura una volta che deve inserire un valore in un punto). Il chiamante/client non ha un modo per utilizzare direttamente un 'Promise' per controllare la pianificazione. –

risposta

11

Il blocco Future { ... } è zucchero sintattico per una chiamata a Future.apply (come sono sicuro che conosci Maciej), passando il blocco di codice come primo argomento.

Guardando allo docs for this method, è possibile vedere che è necessario un numero implicito ExecutionContext - ed è questo contesto che determina come verrà eseguito. Quindi, per rispondere alla tua seconda domanda, il futuro verrà eseguito da qualsiasi ExecutionContext si trova nell'ambito implicito (e, naturalmente, se questo è ambiguo, si tratta di un errore in fase di compilazione).

In molti casi questo sarà quello da import ExecutionContext.Implicits.global, che può essere modificato dalle proprietà di sistema, ma per impostazione predefinita utilizza uno ThreadPoolExecutor con un thread per core del processore.

Tuttavia, la pianificazione è diversa. Per alcuni casi d'uso è possibile fornire il proprio ExecutionContext che applica sempre lo stesso ritardo prima dell'esecuzione. Ma se si desidera che il ritardo sia controllabile dal sito di chiamata, ovviamente non è possibile utilizzare Future.apply in quanto non ci sono parametri per comunicare come deve essere programmato. Suggerirei di inviare le attività direttamente a un esecutore programmato in questo caso.

+0

Yhanks Andrzej: utile come sempre :) – Bober02

3

La risposta di Andrzej copre già la maggior parte della domanda. Vale la pena ricordare che il contesto di esecuzione implicito "predefinito" di Scala (import scala.concurrent.ExecutionContext.Implicits._) è letteralmente a java.util.concurrent.Executor e l'intero concetto di ExecutionContext è un involucro molto sottile, ma è strettamente allineato con il framework executor di Java.

Per raggiungere qualcosa di simile ai futures programmati, come sottolinea Mauricio, dovrai utilizzare le promesse e qualsiasi meccanismo di pianificazione di terze parti.

Non avere un meccanismo comune per questo costruito nei futuri Scala 2.10 è un peccato, ma niente di fatale.

Una promessa è un handle per un calcolo asincrono. Ne crei uno (supponendo ExecutionContext in ambito) chiamando val p = Promise[Int](). Abbiamo appena promesso un intero.
I clienti possono afferrare un futuro che dipende dalla promessa che si sta realizzando, semplicemente chiamando lo p.future, che è solo un futuro di Scala.
Soddisfare una promessa è semplicemente una questione di chiamare p.successful(3), a quel punto il futuro si completerà.

Play 2.x risolve la pianificazione utilizzando promesse e un semplice vecchio Timer Java 1.4.
Here è un collegamento a prova di linkrot all'origine.

Diamo anche un'occhiata alla fonte qui:

object Promise { 
    private val timer = new java.util.Timer() 

    def timeout[A](message: => A, duration: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) 
       (implicit ec: ExecutionContext): Future[A] = { 
    val p = Promise[A]() 
    timer.schedule(new java.util.TimerTask { 
     def run() { 
     p.completeWith(Future(message)(ec)) 
     } 
    }, unit.toMillis(duration)) 
    p.future 
    } 
} 

Questo può quindi essere utilizzato in questo modo:

val future3 = Promise.timeout(3, 10000) // will complete after 10 seconds 

Avviso questo è molto più bello di collegare un Thread.sleep(10000) nel codice, che bloccherà il thread e forzerà un interruttore di contesto.

Da notare in questo esempio anche val p = Promise... all'inizio della funzione e p.future alla fine. Questo è un modello comune quando si lavora con le promesse. Prendilo per significare che questa funzione promette al cliente e avvia un calcolo asincrono per realizzarlo.

Dai uno sguardo al numero here per ulteriori informazioni sulle promesse di Scala. Si noti che utilizzano un metodo minuscolo future dall'oggetto pacchetto concurrent anziché Future.apply. Il primo si limita a delegare a quest'ultimo. Personalmente, preferisco il minuscolo future.