Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delay function execution

Tags:

What is the simplest way to delay function execution in Scala, something like JavaScript's setTimeout? Ideally without spawning thread per delayed execution, i.e. sequential execution. The closest that I was able to find was Akka's Scheduler, but that's an overkill.

For my testing purposes I'm opening thousands of connections, then they get responses in 10 seconds. In node.js it looks like:

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'); 

But what would be the closest Scala version of doing the same? I don't care if res.end is going to be executed in multiple threads or queued in a single one.

like image 567
Oleg Mikheev Avatar asked Jun 22 '13 04:06

Oleg Mikheev


People also ask

What is a delay execution?

defedant is, with intent to obstruct or delay the execution of any decree that may be passed, either about ... with the intention of obstructing or delaying the execution of any decree that may be passed against him.

What is delay () in JavaScript?

Conclusion. setTimeout() is a method that will execute a piece of code after the timer has finished running. let timeoutID = setTimeout(function, delay in milliseconds, argument1, argument2,...); The delay is set in milliseconds and 1,000 milliseconds equals 1 second.

How do you delay something in JavaScript?

The standard way of creating a delay in JavaScript is to use its setTimeout method. For example: console. log("Hello"); setTimeout(() => { console.


Video Answer


1 Answers

Tired of getting flak for answering the question for simplest too simply, here are the standard JVM idioms:

$ 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 

There is no API for scheduling a delayed task in the standard library, but you can make an ExecutionContext with a fixed delay, in order to use 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)) 

Or you can use Akka's scheduler, which is the canonical answer at Scheduled Executor in Scala

The old one-liner:

Simplest is still just future { blocking(Thread.sleep(10000L)); "done" }

but I wanted to place an ad for this guy, which I just came across, which gives you a progress indicator or intermediate value. I kind of wish it had a different name, is all.

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 

Here's an alternative formulation with Either, to calculate a value after a delay. Using Left of course when there is still time 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 
like image 136
som-snytt Avatar answered Oct 28 '22 16:10

som-snytt