例えば、javaのThreadを使って以下のようなコードを実行する。
1 to 10 map( n => (new Thread() {
override def run = {
println("start "+n)
Thread.sleep( 3000 )
println("done "+n)
}
}).start )
結果の出力は、以下のように、ほぼ同時に10個のスレッドがスタートして、
3秒後にそれぞれ終了する。これは、予想通り。
start 10 start 4 start 6 start 2 start 3 start 8 start 9 start 7 start 1 start 5 done 10 done 4 done 6 done 2 done 3 done 8 done 9 done 7 done 1 done 5これをActorを使って書き換える。
1 to 10 map( n => Actor.actor {
println("start "+n)
Thread.sleep( 3000 )
println("done "+n)
})
このコードを実行した結果。
start 1 start 6 start 8 start 7 start 3 start 5 start 2 start 4 done 1 done 6 done 8 start 9 start 10 done 3 done 7 done 4 done 2 done 5 done 9 done 10この結果をみると、最初の8個のスレッドは、ほぼ同時にスタートしているのがわかるが、 残りの2つは、最初にスタートしたスレッドが終わるのを待ってから、3秒後にそれぞれスタートしている。
なぜ?
どうやらこれはActorのプールに関係しているらしい。
詳しくは分からないが、Thread.sleepを使った場合、 並列に実行できるのは、CPUのスレッド数のみのようだ。
それ以上に、並列に実行したいので、Thread.sleepを使わずに、 receiveWithinを使ったらうまくいった。
1 to 10 map( n => Actor.actor {
println("start "+n)
Actor.self.receiveWithin( 3000 ) { case TIMEOUT => {}}
println("done "+n)
})
仕方ないので、この方法でやるかなぁ。
ScalaのActorの中でThread.sleepを使っていたら、どうも平行に処理されていないような気がして調べてみました。
Emacsにclojureの開発を整えた時のメモ。
Emacsのパッケージ管理システムであるMarmaladeをインストールしてみました。