2013-06-22 19 views
16

JavaScriptのsetTimeoutのような、スカラでの関数の実行を遅延させる最も簡単な方法は何ですか?理想的には、遅延実行、すなわち逐次実行ごとにスレッドを生成することなく。私が見つけることができた最も近いものはAkkaのSchedulerでしたが、それは過剰です。遅延関数の実行

私のテスト目的のために、私は何千もの接続をオープンしており、10秒後に応答します。 node.jsでは、次のようになります。

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

しかし、同じことを行うのに最も近いScalaバージョンは何でしょうか? res.endが複数のスレッドで実行されるか、または単一のキューに入れられるかどうかは気にしません。あまりにも単純に最も簡単なのための質問に答えるために非難を得るのはうんざり

+1

可能な複製、私はこの答えは助けわからない:http://stackoverflow.com/a/16629357/1296806ができますが、テストのためジャンキー1オフをしたいかもしれない場合。 –

+0

この他の質問を見ることもできます:http://stackoverflow.com/questions/16359849/scala-scheduledfuture –

答えて

20

、ここでは標準のJVMのイディオムです:そこ標準ライブラリに遅延タスクをスケジュールするためのAPIはありませんが、あなたが作ることができ

$ 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 = [email protected] 

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 = [email protected] 

scala> x.schedule(new Callable[Int]() { def call = { println("Ran"); 42 }}, 1L, TimeUnit.SECONDS) 
res3: java.util.concurrent.ScheduledFuture[Int] = java.[email protected]3ab0f534 

scala> Ran 

スクロールFutureを使用するには固定遅延のExecutionContextを使用してください。

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 = [email protected] 

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

それともScheduled Executor in Scala

古いワンライナーで標準的な答えであるアッカのスケジューラ、使用することができます。

最も簡単にはまだちょうどfuture { blocking(Thread.sleep(10000L)); "done" }

ですが、私は配置したいですあなたが進歩インジケータまたは中間値を与える、私がちょうど出会ったこの男のための広告。私はそれが別の名前を持っていたらいいなあと思っています。

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] = [email protected] 

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 

ここでは遅延の後の値を計算するために、どちらか一方の代わりの式を使用しています。 Leftを使用してください。もちろん、まだ時間がある場合は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]] = [email protected] 

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 
+6

10秒間何千ものスレッドがスリープ状態になることはありませんか? –

+3

ノンブロッキングソリューションはありますか? –

+0

@OlegMikheevはい。 –

関連する問題