8

最近、私のプロジェクトで、いくつかのタスクを非同期で実行する必要がありました。Tomcat 内で Spring を使用して Web アプリケーションを実行しているため、Spring が提供する ThreadPoolTask​​Executor が解決策でした。

しかし、アーキテクトは、webapp でスレッドを生成する/スレッド プールを持つことは恐ろしい/禁止されている/絶対的な悪であると述べて、いくつかの異議を唱えました。

ネットと StackOverflow を少し調べてみたところ、Java EEコンテナー内に独自のスレッド プールを配置するのは悪い習慣であることがわかりました。その理由は、独自のスレッド プールがある場合、コンテナーはそれを認識せず、リソースを適切に管理できないというものでした。これは、Web アプリケーションのホット デプロイを行う必要がある場合に特に重要です。

ここでのユース ケースは、Tomcat 内で実行される Spring Web アプリケーションです。まず、Spring コンテナを軽いJava EEコンテナのように考えてよい でしょうか。この場合、スレッドプールのライフサイクルを直接管理するのは Spring であり、アプリケーション自体ではありませんね。

第 2 に、ホット デプロイメントの議論はこの構成にも適用されますか?

はい、Tomcat でワーカー プールを直接宣言し、JNDI を介して Spring に注入できることはわかっています。ただし、Spring が提供する直接の ThreadPoolTask​​Executor 機能と比べると少し面倒です。

私の最後の質問は、アーキテクトの異議は私の場合に関連していますか?

このトピックに関するご提案やご意見をお寄せいただきありがとうございます。

4

2 に答える 2

11

悪にはさまざまなレベルがあり、すべての状況で実際に悪とみなされるわけではありません。

プールを使用する代わりに必要に応じてスレッドを作成することは、一般的に悪と見なされますが、これは Java EE だけに当てはまるわけではなく、ほぼすべての種類のサーバー アプリケーションに当てはまります。

Java EE では、特に EJB コンテナー内で独自のスレッドを作成することは許可されていません。これは特に、Java EE コンテナがコンテキスト データを目に見えない形でスレッド ローカル ストレージに格納する可能性があるためです。これは、コードが独自のスレッドで実行を開始すると失われます。

ただし、Web コンテナーにはそのような制限はなく、仕様によれば、スレッド プールを持つことは多かれ少なかれ合法です。これが、たとえば、EJB モジュールのみが使用されている場合でも、人々が EAR 内の Web モジュールから Quartz を起動していた理由、または Web モジュール内のコードがコールバック リスナーを管理されていない JMS キューに登録できたのに、EJB ができなかった理由です。これを行う。

ただし、実際には、(プールを介して) スレッドを作成することは、実際にはほとんど常に機能します。たとえば、EJB を使用する場合は、これらのスレッドで実行されているコードで JNDI からインスタンスを取得する必要があり、EJB の参照を渡さないことを念頭に置いている限りです。それらのアンマネージ スレッドに。もちろん、プールをシャットダウンするように注意する必要がありますが、Java EE のほぼすべての種類の起動リスナーには、これを実行できる対応するシャットダウン リスナーがあります。

Java EE には、独自のプールを作成する必要性を軽減する公式の方法がいくつかあります。

  • @Asynchronous アノテーション
  • JMS メッセージの送信と MDB での処理
  • を使用するAsyncContext#start()(これは一般的な用途が限られています。「What's the Purpose of AsyncContext.start(...) in Servlet 3.0? 」を参照してください)
  • ワークマネージャー API の使用 (これは実際には JCA コネクターのベンダーが使用することを意図しているため、エンドユーザー向けに簡素化されていません。http://www.adam-bien.com/roller/abien/entry/easy_threading_and_concurrency_inおよびhttp:/を参照してください) /connectorz.adam-bien.com )

ただし、一部のアルゴリズムでは、デッドロックの可能性を防ぐために個別のスレッド プールが必要です。どの Java EE ソリューションも、作業が異なるスレッド プールによって行われるという絶対的な保証を提供するものではないため、独自のプールを作成する以外にもっともらしい方法がない場合があります。

したがって、最後の状況では、独自のスレッドプールを作成するよりも、コードを開いてデッドロックする方が実際には悪いことです。

于 2012-08-10T21:09:32.927 に答える
2

Java EEアプリケーション内に自己管理されたTaskExecutorsを持つことは、適切に分離されていれば悪い習慣ではありません。非同期タスクを分離されたインスタンスに分離すると、新しいレベルの複雑さと新しい依存関係が発生し、パフォーマンスが低下します。

コンテナーは多くのインスタンス (静的参照など) を認識/所有していないため、管理されていないアーキテクト引数はもちろん null 可能であり、 @Configuration クラス内または spring 構成ファイル内で実行者自体を構成できます。少なくとも、コンテナーによって管理されるエグゼキューター自体。

さらに、Spring 自体は、スケジュールされたメソッドを実行するいくつかのメソッドを公開しています。

ホット デプロイの依存関係は、作業キューの構成方法と、非同期タスクがそれらを処理する方法によって異なります。

于 2012-08-08T21:07:12.713 に答える