Java EEコンテナーでのスレッドの生成が推奨されないのはなぜですか?


120

Java EE開発について最初に学んだことの1つは、Java EEコンテナー内に自分のスレッドを生成してはいけないということです。でも考えてみると、その理由はわかりません。

それが推奨されない理由を明確に説明できますか?

ほとんどのエンタープライズアプリケーションには、メールデーモン、アイドルセッション、クリーンアップジョブなどの非同期ジョブが必要だと思います。

それで、実際にスレッドを生成してはならない場合、必要なときにそれを行う正しい方法は何ですか?


4
非同期タスクは通常、JMSメッセージングとMDBを使用して実行されます。
Ken Liu

5
JSR 236がコンテナーに実装されれば、この問題はすぐに過去のものになるはずです。
letmaik 2013

5
スレッドが他のエンタープライズリソースにアクセスできるように、2番目のスレッドはコンテナによって作成および管理される必要があるため、推奨さませんでした。Java EE7では、エンタープライズ環境でスレッドを作成するための標準的で正しい方法があります。Concurrency Utilsを使用することで、新しいスレッドが作成され、コンテナーによって管理され、すべてのEEサービスが利用可能であることを保証します。ここの
Chris Ritchie

JSF / EJBの視点でいくつかの正しい方法はここで見つけることができます:stackoverflow.com/q/6149919
BalusC

回答:


84

環境内のすべてのリソースはサーバーによって管理され、監視される可能性があるため、推奨されません。また、スレッドが使用されているコンテキストの多くは、通常、実行のスレッド自体に関連付けられています。独自のスレッド(一部のサーバーでは許可されていないと思われる)を単純に開始した場合、他のリソースにアクセスできません。つまり、InitialContextを取得してJNDIルックアップを実行し、JMS接続ファクトリやデータソースなどの他のシステムリソースにアクセスすることはできません。

これを「正しく」行う方法はいくつかありますが、使用しているプラ​​ットフォームによって異なります。

commonj WorkManagerは、WebSphereとWebLogicだけでなく他にも共通です。

詳細はこちら

そしてここ

また、今朝からこれをいくらか複製します

更新:この質問と回答は2009年のJava EEの状態に関連していることに注意してください。それ以降、状況は改善されています!


1
InitialContextを取得して、JNDIルックアップを実行して、JMS接続ファクトリやデータソースなどの他のシステムリソースにアクセスすることはできません。スレッドを開始するときにデータソースを
挿入

6
これで、コアJava EE APIでスレッドを作成するための標準的で正しい方法があります。Concurrency Utilsを使用することで、新しいスレッドが作成され、コンテナーによって管理され、すべてのEEサービスが利用可能であることを保証します。ここここの
Chris Ritchie

@ChrisRitchie先端をありがとう。JBoss AS / IBM WASのみがJava EE 7をサポートしている場合... :-(
asgs

1
@asgs WildFly 8(JBoss ASの新しい名前)はJava EE 7をサポートします。IBMはJava EE 6認定済みの認定です
Chris Ritchie

34

EJBの場合、これは推奨されないだけでなく、仕様で明示的に禁止されています

エンタープライズBeanは、複数のインスタンスの実行を同期するためにスレッド同期プリミティブを使用してはなりません。

そして

エンタープライズBeanはスレッドの管理を試みてはなりません。エンタープライズBeanは、スレッドの開始、停止、一時停止、再開、またはスレッドの優先順位や名前の変更を試みてはなりません。エンタープライズBeanはスレッドグループの管理を試みてはなりません。

その理由は、EJBが分散環境で動作することを意図しているためです。EJBは、クラスター内のあるマシンから別のマシンに移動される場合があります。スレッド(およびソケットとその他の制限された機能)は、この移植性に対する大きな障壁です。


3
Java EE7 Concurrency Utilsは、エンタープライズ環境でスレッドを作成する正しい方法を提供します。ここここの
Chris Ritchie

1
@ダンスレッドが、EJBをカスター内のあるマシンから別のマシンに移動する際の移植性に対する大きな障害となる理由を教えていただけますか?
Geek

13

独自のスレッドを生成してはならないのは、これらのスレッドがコンテナによって管理されないためです。コンテナは、初心者の開発者が想像するのが難しいと思われる多くのことを処理します。たとえば、スレッドプーリング、クラスタリング、クラッシュリカバリなどはコンテナによって実行されます。スレッドを開始すると、それらのいくつかが失われる可能性があります。また、コンテナを使用すると、実行されているJVMに影響を与えることなくアプリケーションを再起動できます。コンテナーの制御外にスレッドがある場合、これはどのように可能ですか?

これが、J2EE 1.4からタイマーサービスが導入された理由です。詳細については、この記事を参照してください。


2
JSR 236は、Java EE 7以降でスポーンスレッドをサポートする機能を追加しました。この兄弟のChris Ritchieによる回答を参照してください。
バジルブルク2016年


2

いつでも、コンテナにデプロイメント記述子の一部として開始するように指示できます。これにより、必要なメンテナンスタスクを実行できます。

ルールに従う。あなたはいつかあなたが喜んだでしょう:)


2

ブループリントによると、Java EEコンテナーではスレッドは禁止されています。詳細については、ブループリント を参照してください。


2

そうしないという本当の理由はありません。私は問題なくWebアプリケーションでQuarzSpringを使用しました。また、並行フレームワークjava.util.concurrentを使用することもできます。独自のスレッド処理を実装する場合は、theadsをデーモンに設定するか、独自のデーモンスレッドグループを使用して、コンテナがいつでもWebアプリケーションをアンロードできるようにします。

ただし、Beanスコープのセッションリクエストは、生成されたスレッドでは機能しません。また、他のコードで実行しThreadLocalても、そのままでは機能しません。自分で生成したスレッドに値を転送する必要があります。


1

正しく行うのが容易ではないという事実を除いて、それが推奨されないことを私は読んだことがありません。

これはかなり低レベルのプログラミングであり、他の低レベルのテクニックと同様に、正当な理由があるはずです。ほとんどの同時実行性の問題は、スレッドプールなどの組み込み構造を使用すると、はるかに効果的に解決できます。


7
実際、仕様により禁止されています。
Ken Liu

1

EJBでいくつかのスレッドを生成し、問題が発生する予定のEJBをコンテナーでアンロードまたは更新しようとした場合に私が見つけた1つの理由。ほとんどの場合、スレッドを必要としない別の方法があるので、「いいえ」と言ってください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.