CLOVER🍀

That was when it all began.

ふと気付くと、scala.concurrent.pilibオブジェクトが非推奨に…

Scala 2.9.0.1のAPIドキュメントを眺めていて、ふとscala.concurrentパッケージのpilibオブジェクトがdeprecatedになっているの気付きました。

しかも、「use actors instead(Actorに置き換わりました)」ですと?pilibオブジェクトとActorライブラリはけっこうな間、標準ライブラリに一緒にいたと思うのですがねぇ。その他、MailBoxとかの同じようにActorライブラリと被っているクラスは軒並み非推奨に。Parallel Collectionsも入ったことですし、並行プログラミング関連のライブラリを整理したくなったのでしょうか?

pilibオブジェクトは、spawnの書かせ方がカッコよかったのですが(笑)。

同じくscala.concurrentパッケージのopsオブジェクトは残っているので、こちらで久々に遊んでみましょう。備えているメソッド数は少なく、以下の4つ。

  • future
  • par
  • spawn
  • replicate(非推奨。collection.parallel.ParIterable.foreachに置き換わったとな)

どれも簡易的なメソッドなので、あんまり高機能ではなさそうです。特に、タイムアウトが値として指定できないのがちょっと…。

まずは、REPLを起動してopsオブジェクトをインポート。

$ scala
Welcome to Scala version 2.9.0.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_24).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.concurrent.ops._
import scala.concurrent.ops._

future。

scala> val f = future("Hello World")
f: () => java.lang.String = <function0>

scala> f()
res0: java.lang.String = Hello World

戻り値としてAを返す関数が返ってくるので、()で評価して値を取り出します(() => Aが戻り値ってことですね)。

par。

scala> def getX: String = "X"
getX: String

scala> def getY: String = "Y"
getY: String

scala> par(getX, getY)
res2: (String, String) = (X,Y)

何らかの値を戻す、引数なしの2つの関数を引数に取り、結果をタプルとして返します。両方の結果が取得できるまで、待ち合わせを行います。

例えば、getYを以下のように変更して実行すると…

scala> def getY: String = {
     |   println("getY waiting...")
     |   Thread.sleep(3000L)
     |   "Y"
     | }
getY: String

scala> par(getX, getY)
getY waiting...
res3: (String, String) = (X,Y)

getYの実行が終わるまで、ブロックすることになります。

最後、spawn。

scala> spawn(println("Hello World"))

scala> Hello World
scala> spawn {
     |   println("Spawn waiting...")
     |   Thread.sleep(3000L)
     |   println("Hello World")
     | }

scala> Spawn waiting...


scala> Hello World

引数に、引数なしの関数を1つ取り、非同期に実行します。手軽にスレッドを開始するメソッドで、走り出したスレッドが戻ってこないので、待ち合わせはできません(クロージャーの自由変数でThread.currentThreadを取れば、もちろんjoinなどで待ち合わせはできますが、それも微妙…)。

replicateは非推奨なので、割愛〜。

まあ、気軽に使う分には便利かな。