Java SE 7徹底理解の2回目である今月は、並行処理のフレームワークについて紹介していきます。
Javaは1.0がリリースされた当初から、スレッドを使用することができました。筆者もJava 1.0で簡単にスレッドが使えることに感動したことを覚えています。
しかし、スレッドを安易に使ってしまうと、デッドロックやデータの破壊を引き起こしかねません。スレッドクラスは簡単に使えるものの、使いこなすには並列/並行処理についての適切な知識を必要としたのです。
そこで、より簡単に並列/並行処理を使うためのフレームワークであるConcurrency UtilitiesがJ2SE 5.0で導入されました。
Concurrency Utilitiesは非同期処理APIや、スレッドセーフで高性能な並行コレクション、ラッチやセマフォなどのロック機構、アトミック処理など並列/並行処理のためのさまざまな機能が含まれていました。
Concurrency Utilitiesでは非同期処理にExecutorインタフェースを使用します。また、スレッドプールも提供されています。 このためThreadクラスを直接使う必要もなくなり、並列/並行処理を行なうためのハードルがかなり低くなったのです。
しかし、その後ハードウェアのトレンドが大きく変わりました。J2SE 5.0がリリースされたのが2004年。当時はCPUのクロックの上昇が鈍くなり、その代わりにマルチコアのCPUが登場しはじめました。
今では、家庭用のPCでも4コアは当たり前に使われていますし、サーバではより多くのコアを使用しています。
このようにCPUのアーキテクチャが変化を遂げているのですから、ソフトウェアもそれに対応しなくてはいけません。つまり、複数のコアを遊ばせておかないようにする必要があります。
そのためには、タスクをより細分化して、複数のコアにまんべんなく処理を行なわせなければいけません。
ところがここで問題があります。
Concurrency Utilitiesで導入されたExecutorインタフェースは細粒度のタスク処理には適していないのです。
Executorインタフェースはある程度粒度の大きいタスクを想定して設計されています。このため、粒度が細かくなるとオーバヘッドが大きくなってしまい、パフォーマンスが落ちてしまいます。
そこで、登場するのがJava SE 7で導入される予定のFork/Join Frameworkです。
Concurrency UtilitiesはJCPのJSR 166において仕様策定が行なわれてきました。Fork/Join Frameworkは新たなJSRを起こすのではなく、JSR 166のアップデートとして仕様策定されています。両者を区別するために、Fork/Join FrameworkはJSR 166yと呼ばれます。
JSR 166yはJSR 166と同様にDoug Lea氏が中心になって仕様策定が行なわれています。