S2JMS 開発記 WorkManager と CountDownLatch

S2JMS 開発記といいつつ,当分は S2JCA 開発記.
まずは「10. Work Management」から.


ここでの主要な存在は javax.resource.spi.work.WorkManager です.
これは java.util.concurrent.Executor と近い代物で,重めの処理をバックグラウンドのスレッドで実行してもらうためのもの.
話を JMS による非同期メッセージングに限定して書くと,メッセージを受信した JMS リソースアダプタはそれを javax.jms.MessageListener を実装したアプリケーションっていうか MDB に渡して処理してもらうのですが,その際にメッセージを受信したスレッドではなく,アプリケーションサーバが管理するスレッドで処理してもらうことが想定されているっぽい.
そのために使われるのが WorkManager
実際にはメッセージの処理以外のことでもなんでもありで,とにかくリソースアダプタは自前でスレッド起こしたりせずに,何かあったら WorkManager にお願いする次第.


んで,WorkManager にはこんなメソッドがあります.

  • doWork(Work work)
  • startWork(Work work)
  • scheduleWork(Work work)

WorkRunnable を拡張したもので,アプリケーションサーバが提供するスレッド上で実行する処理を表します.
それぞれのメソッドの複雑版もあるのですが,これらの違いは

doWork(Work)
別スレッドで Work の実行が終了した時点でリターンする.
startWork(Work)
別スレッドで Work の実行が開始された時点でリターンする.
scheduleWork(Work)
WorkManagerWork を受け付けた時点でリターンする.

となっています.
つまり,単純にスレッドプールに Work をキューイングして終わりじゃなくて,開始時点や終了時点で同期をとらないといけないわけですね.


こういうのって,自分で同期してもたいした手間ではないのですが,これまで J2SE1.4 前提だったために使う機会の無かった java.util.concurrent パッケージをチェックしてみたら,そのものズバリなクラスがありました.
java.util.concurrent.CountDownLatch です.


こいつは整数の値を持っていて,await() メソッドを呼び出すと整数値が 0 になるまでブロックします.
別のスレッドが countDown() メソッドを呼び出すと整数値が -1 され,0 になれば await() しているスレッドが起こされます.
なので,doWait(Work) では 2,startWork(Work) では 1,scheduleWork(Work) では 0 に設定した CountDownLatch を使って,Work の実行前後に countDown() を呼び出すようにすれば簡単に実装できそう (整数値が 0 の時に countDown() を呼び出しても問題なし).
昔 (Doug Lea の) はバイナリの Latch しかなかった気がするけど,こっちの方が強力ですね.
スレッドプールもいくつかの実装が用意されているし,便利そうだなぁ java.util.concurrent パッケージ.
Tiger を使う機会が無くてかなーり出遅れたけど,これらもうまく使えるようにならなきゃ.


とりあえず,正月休み中に「10. Work Management」を終わらせたい今日この頃であります.