オーバーヘッドがあまりない、scala の別のスレッドで非常に単純なタスクを実行する方法があるかどうか疑問に思っていました。
基本的に、任意の数のタスクの実行を処理できるグローバルな「エグゼキューター」を作成したいと考えています。その後、executor を使用して、追加の構成を構築できます。
さらに、クライアントがブロッキングまたは非ブロッキングの考慮事項を考慮する必要がなければよいでしょう。
Scala アクター ライブラリは Doug Lea FJ のものの上に構築されており、私が達成しようとしていることをある程度サポートしていることも知っています。ただし、私の理解では、「アクター プール」を事前に割り当てて達成する必要があります。
このためのグローバル スレッド プールを作成することは避けたいと思います。
簡単な例を次に示します。
import concurrent.SyncVar
object SimpleExecutor {
import actors.Actor._
def exec[A](task: => A) : SyncVar[A] = {
//what goes here?
//This is what I currently have
val x = new concurrent.SyncVar[A]
//The overhead of making the actor appears to be a killer
actor {
x.set(task)
}
x
}
//Not really sure what to stick here
def execBlocker[A](task: => A) : SyncVar[A] = exec(task)
}
次に、exec の使用例を示します。
object Examples {
//Benchmarks a task
def benchmark(blk : => Unit) = {
val start = System.nanoTime
blk
System.nanoTime - start
}
//Benchmarks and compares 2 tasks
def cmp(a: => Any, b: => Any) = {
val at = benchmark(a)
val bt = benchmark(b)
println(at + " " + bt + " " +at.toDouble / bt)
}
//Simple example for simple non blocking comparison
import SimpleExecutor._
def paraAdd(hi: Int) = (0 until hi) map (i=>exec(i+5)) foreach (_.get)
def singAdd(hi: Int) = (0 until hi) foreach (i=>i+5)
//Simple example for the blocking performance
import Thread.sleep
def paraSle(hi : Int) = (0 until hi) map (i=>exec(sleep(i))) foreach (_.get)
def singSle(hi : Int) = (0 until hi) foreach (i=>sleep(i))
}
最後にサンプルを実行します (HotSpot がウォームアップできるように、数回実行する必要があるかもしれません):
import Examples._
cmp(paraAdd(10000), singAdd(10000))
cmp(paraSle(100), singSle(100))