EJBとかJMSのような実践的なJavaEEは今まで触らず、もっぱらServletプログラミングばかり触ってましたが、最近になって「新しいJavaEEでは非同期処理がサポートされた!」とか目にしまして、「アレ?JavaEE環境ってスレッド作成しちゃ駄目だったの?」と今頃になって気になり、ちょっと調べてみました。
JavaEE7使おうぜ! or JavaEEコンテナ環境を当てにせず独自実装で頑張ろう!
JavaEE5以前は、ServletやEJBなどJavaEE側でコンテナとして管理される仕組みではスレッドはなるべくコンテナ側で管理される仕組みを目指しているため、アプリ側で好き勝手にスレッド作るのは好ましくないようでした。JavaEE6になりServletで一部、非同期処理に対応したためスレッドっぽく使えるようになったようです。そのような状況でしたので、JavaEE7になり正式にスレッド生成をサポートするようになったのが、特にニュースになったようです。
「好ましくない」という言い方ですが、モノによっては「禁止」まで名言されてたりされてなかったりするようです。EJBだと以前の仕様では禁止と明記されてたり、Servletの仕様だと「好ましくない」にとどまってたり微妙に有耶無耶。ただ、あんまり「new Threadしたらコンテナ側からエラーで怒られた!」とかいう話は見当たらなかったので、コンテナ側のポリシー設定で禁止してるとかそういう話はみかけませんでした。(もしかしたら一部のJ2EEコンテナ製品ではそうした設定があったりして、単に検索で引っかからなかっただけかも)
理解した範囲で、技術的な背景を説明するなら、EJBにせよServletにせよ、スレッドローカルにコンテナ側で生成したオブジェクトを入れてる仕組みが多いようです。そのため、アプリ側で好き勝手に作られたスレッド中から、本来ならコンテナ側で管理してるオブジェクトを参照していたりすると、スレッドが動くタイミングではコンテナ側でクリアしていてNullPointerExceptionになってしまったりと、予測できない動きになってしまうケースがあるようです。
そのため、スレッドの作成をするのであればJavaEE環境の恩恵は受けられないことを前提として、必要なオブジェクトは自分たちでちゃんと引き継いで、スレッドの管理も含めて自分たちで面倒見てくださいね、何かあってもJavaEE側は知りませんよ、というスタンスみたいです。
分かりやすかった日本語解説ページ:
Servletの世界の場合ですと、ServletContextListener使うのが地雷回避っぽいですね。
stackoverflowでもチラホラトピックに挙がってました。
JavaEE6に含まれた Servlet 3.0 において、非同期APIが導入されました。とはいえ、スレッド生成がサポートされた訳ではないようです。
"Concurrency Utilities for JavaEE(JSR-236)"の導入により、正式にスレッド生成をサポート・・・つまり、JavaEEコンテナ側でスレッド管理されて、JavaEEコンテナ側で管理されてるリソースが生成されたスレッドから参照可能になる・・・ということでよろしいでしょうか・・・。
JSR-236とか目を通してないし、多分現場レベルでの情報が出てくるのはこれからだと思いますので、今日のところはここまで。
コメント