scala - tiempo - sleep javascript
EjecuciĆ³n de la funciĆ³n de retardo (1)
Cansado de recibir críticas por responder a la pregunta de la manera más sencilla, aquí están los modismos JVM estándar:
$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_65).
Type in expressions for evaluation. Or try :help.
scala> import java.util.{Timer,TimerTask}
import java.util.{Timer, TimerTask}
scala> val timer = new Timer
timer: java.util.Timer = java.util.Timer@2d9ffd6f
scala> def delay(f: () => Unit, n: Long) = timer.schedule(new TimerTask() { def run = f() }, n)
delay: (f: () => Unit, n: Long)Unit
scala> delay(() => println("Done"), 1000L)
scala> Done
scala> import java.util.concurrent._
import java.util.concurrent._
scala> val x = Executors.newScheduledThreadPool(2)
x: java.util.concurrent.ScheduledExecutorService = java.util.concurrent.ScheduledThreadPoolExecutor@2c5d529e
scala> x.schedule(new Callable[Int]() { def call = { println("Ran"); 42 }}, 1L, TimeUnit.SECONDS)
res3: java.util.concurrent.ScheduledFuture[Int] = java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@3ab0f534
scala> Ran
No hay una API para programar una tarea retrasada en la biblioteca estándar, pero puede hacer un ExecutionContext
con una demora fija para usar Scala Future
.
scala> import scala.concurrent._
import scala.concurrent._
scala> implicit val xx = new ExecutionContext() {
| def reportFailure(t: Throwable) = t.printStackTrace()
| def execute(r: Runnable) = x.schedule(new Callable[Unit]() { def call = r.run() }, 1L, TimeUnit.SECONDS)
| }
xx: scala.concurrent.ExecutionContext = $anon$1@40d3ab8b
scala> Future(println("hello"))
res4: scala.concurrent.Future[Unit] = List()
scala> hello
scala> Future(42)
res5: scala.concurrent.Future[Int] = List()
scala> .value
res6: Option[scala.util.Try[Int]] = Some(Success(42))
O puede usar el programador de Akka, que es la respuesta canónica en el Ejecutor Programado en Scala
El viejo de una sola línea:
Lo más simple es solo el future { blocking(Thread.sleep(10000L)); "done" }
future { blocking(Thread.sleep(10000L)); "done" }
pero quería colocar un anuncio para este tipo, que acabo de encontrar, que te da un indicador de progreso o valor intermedio. Me gustaría que tuviera un nombre diferente, eso es todo.
scala> import concurrent._
import concurrent._
scala> import ExecutionContext.Implicits._
import ExecutionContext.Implicits._
scala> import duration._
import duration._
scala> val deadline = 60.seconds.fromNow
deadline: scala.concurrent.duration.Deadline = Deadline(38794983852399 nanoseconds)
scala> new DelayedLazyVal(() => deadline.timeLeft.max(Duration.Zero), blocking {
| Thread.sleep(deadline.timeLeft.toMillis)
| Console println "Working!"
| })
res9: scala.concurrent.DelayedLazyVal[scala.concurrent.duration.FiniteDuration] = scala.concurrent.DelayedLazyVal@50b56ef3
scala> res9()
res10: scala.concurrent.duration.FiniteDuration = 23137149130 nanoseconds
scala> res9.isDone
res11: Boolean = false
scala> res9()
res12: scala.concurrent.duration.FiniteDuration = 12499910694 nanoseconds
scala> res9()
res13: scala.concurrent.duration.FiniteDuration = 5232807506 nanoseconds
scala> Working!
scala> res9.isDone
res14: Boolean = true
scala> res9()
res15: scala.concurrent.duration.FiniteDuration = 0 days
Aquí hay una formulación alternativa con O, para calcular un valor después de un retraso. Usando la Left
por supuesto, cuando todavía hay tiempo Left
.
scala> new DelayedLazyVal(()=> if (deadline.hasTimeLeft) Left(deadline.timeLeft) else
| Right("Working!"), blocking(Thread.sleep(deadline.timeLeft.toMillis)))
res21: scala.concurrent.DelayedLazyVal[Product with Serializable with scala.util.Either[scala.concurrent.duration.FiniteDuration,String]] = scala.concurrent.DelayedLazyVal@78f9c6f2
scala> res21()
res22: Product with Serializable with scala.util.Either[scala.concurrent.duration.FiniteDuration,String] = Left(28553649064 nanoseconds)
scala> res21()
res23: Product with Serializable with scala.util.Either[scala.concurrent.duration.FiniteDuration,String] = Left(9378334087 nanoseconds)
scala> res21.isDone
res24: Boolean = false
scala> res21()
res25: Product with Serializable with scala.util.Either[scala.concurrent.duration.FiniteDuration,String] = Right(Working!)
scala> res21.isDone
res26: Boolean = true
¿Cuál es la forma más sencilla de retrasar la ejecución de la función en Scala, algo como el setTimeout
de JavaScript? Lo ideal sería sin subprocesos por ejecución retrasada, es decir, ejecución secuencial. Lo más cercano que pude encontrar fue el Scheduler de Akka, pero eso es una exageración.
Para mis propósitos de prueba, estoy abriendo miles de conexiones, luego obtienen respuestas en 10 segundos. En node.js se ve como:
http.createServer(function (req, res) {
res.writeHead(200, {''Content-Type'': ''text/plain''});
setTimeout(function() {res.end(''Hello World/n'');}, 10000 );
}).listen(8080, ''127.0.0.1'');
Pero, ¿cuál sería la versión más cercana de Scala de hacer lo mismo? No me importa si res.end
se ejecutará en varios subprocesos o se pondrá en cola en uno solo.