Ecco una versione che mostra quanto grave è il blocco fallback
.
Si noti che l'executor è a thread singolo e si stanno creando molti fallback.
@cmbaxter ha ragione, il timeout principale non dovrebbe essere timeout * futures.size
, dovrebbe essere più grande!
@cmbaxter ha anche ragione che si desidera pensare non bloccante. Una volta che lo fai, e vuoi imporre dei timeout, allora sceglierai un componente timer per quello, vedi la sua risposta collegata (anch'essa collegata dalla tua risposta collegata).
Detto questo, mi piace ancora lo my answer from your link, nella misura in cui sedersi in attesa che la prossima cosa che dovrebbe scadere è davvero semplice.
Richiede solo un elenco di future, i loro timeout e un valore di riserva.
Forse c'è un caso d'uso per questo, come ad esempio una semplice applicazione che a pochi isolati per alcuni risultati (come il test) e non devono uscire prima che i risultati sono in
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executors
import java.lang.System.{ nanoTime => now }
object Test extends App {
//implicit val xc = ExecutionContext.global
implicit val xc = ExecutionContext fromExecutorService (Executors.newSingleThreadExecutor)
def timed[A](body: =>A): A = {
val start = now
val res = body
val end = now
Console println (Duration fromNanos end-start).toMillis + " " + res
res
}
println("Creating futureList")
val timeout = 1500 millis
val futures = List(1000, 1500, 1200, 800, 2000) map { ms =>
val f = future {
timed {
blocking(Thread sleep ms)
ms toString
}
}
Future firstCompletedOf Seq(f, fallback(timeout))
}
println("Creating waitinglist")
val waitingList = Future sequence futures
println("Created")
timed {
val results = Await result (waitingList, 2 * timeout * futures.size)
println(results)
}
xc.shutdown
def fallback(timeout: Duration) = future {
timed {
blocking(Thread sleep (timeout toMillis))
"-1"
}
}
}
Che cosa è successo:.
Creating futureList
Creating waitinglist
Created
1001 1000
1500 -1
1500 1500
1500 -1
1200 1200
1500 -1
800 800
1500 -1
2000 2000
1500 -1
List(1000, 1500, 1200, 800, 2000)
14007()
Come curiosità, come 'HashedWheelTimer' è più efficiente di' TimerTask' o 'newScheduledThreadPoolExecutor'? Entrambi fanno lo stesso lavoro. – Jatin
@ Jatin, suppongo che puoi dare un'occhiata a questo link per maggiori informazioni: http://stackoverflow.com/questions/15347600/which-is-more-efficient-nettys-hashedwheeltimer-or-quartzs-scheduler. Ma nel suo cuore, l'aggiunta di più attività non dovrebbe consumare più risorse. Dovrebbe essere un timer basato sul tempo più costante (in termini di risorse di sistema consumato), quindi qualcosa come un 'Timer' e' TimerTask'. Per un sistema ad alto throughput in cui si pianificheranno un sacco di attività basate sul timeout di breve durata, è una soluzione migliore a causa delle richieste di utilizzo costante delle risorse. – cmbaxter
Ma come 'STPE' con' coresize' '1' consuma più risorse rispetto a' HashedWheelTimer'? Mi dispiace ma non capisco. 'STPE' ha più tempo di inserimento a causa dell'heap interno' O (log (n)) 'ma meno tempo di tick. Può spiegare, per favore, – Jatin