仕事でJava使ってるわけでもないし、っていうかJava触ってたのって研究室でのごく一時期だけでJavaのジャの字も分かっていないのだけど、「体調が悪いときはひたすらダラダラインプットする」といういつも通りの行動を取っていたら「Java並行処理プログラミング」に突き当たった。という。
ちなみに、上の本より先の内容はないです。nioとかないです。結構今更な内容かと。
とりあえず
concurrent系のパッケージにあるデータ構造使う(ConcurrentHashMapとかBlockingQueueとか)。本の前半の「自分でsynchronizedしてほげほげする」の部分は噛ませ犬。いわゆる「ロックで効率よくthread safeな設計するのは難しいですよ」的な。
Runnable
http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/Runnable.html
何がしたいのか分かりにくいけど、要はとある無名関数 or ブロック的なものを1つのスレッドに結びつけて実行するためのインタフェースぽい。計算した値は返せない。(内部で共有変数に突っ込むとかはできる)
Callable
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/Callable.html
値を返せるRunnable、っぽい。基本的にはこっちのほうがうれしいっぽい。ちなみにRunnableもCallableも、threadとか無視してrun()とかcall()を直で呼んじゃうこともできる。Callable
Future
いわゆるFutureパターン。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/Future.html
Future
getしたときにまだ内部の値がない時は値が計算されるまでblockする。cancelとかもできる。
FutureTask
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/FutureTask.html
RunnableとFutureを両方実装している。
Futureは「値をラップする何か」だけど、FutureTaskは「値を生成するCallableをラップする何か」。
なので、Callableから生成する。
BlockingQueue
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/BlockingQueue.html
threadによるいわゆるproducer-consumerパターンの実装を楽にしてくれるキュー。dequeueすると、データがある場合はデータが取れ、データない場合はデータ入るまでブロック。的な。サイズ制限をつけると、満杯のときにenqueueするとブロック。たぶんプログラム内部におけるジョブキュー的に使う。
Executor
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/Executor.html
昔この辺を調べたときはこれがよく分からなかったんだけど、どうやらJobのsubmitとJobの実行を分離するためのものらしい。
submitする部分はここで
Runnable task = new Runnable() { public void run() { // do something } }; executor.execute(task);
Executorのサブクラスでexecuteをオーバライドしてホゲホゲ。的な。
ExecutorService
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/ExecutorService.html
ExecutorはRunnableしかexecuteできないのが悲しい。それでは計算結果が受け取れないではないか。
そこでExecutorService。ExecutorServiceのsubmitはCallable
やったねたえちゃん、値が取れるよ!
ちなみにFutureTaskはRunnableをimplementしているので、ExecutorにFutureTask経由でCallableを渡す、という方法で値を得ることもできるっぽい。
ExecutorCompletionService
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/ExecutorCompletionService.html
内部にExecutorとBlockingQueueをもち、Futureのdoneをオーバライドしてその中で自身をBlockingQueueにenqueueすることで、要は終わったJobから順にBlockingQueueから取り出す、という能力をExecutorに付け加える、的な。
Atomicほげほげ
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/atomic/AtomicInteger.html
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/atomic/AtomicReference.html
Atomicほげほげを使うと、JavaレイヤからCAS命令を明示的に行うことができる。concurrentパッケージのコンテナも、これらを使って実装されているものがあるとかなんとか。