ステートレス セッション Bean をプールする理由は何ですか?
-
02-07-2019 - |
質問
Java のステートレス Bean は、クライアントからの 2 つの呼び出しの間は状態を保持しません。つまり、簡単に言うと、ビジネス メソッドを備えたオブジェクトと考えることができます。各メソッドはパラメータを受け取り、結果を返します。メソッドが呼び出されると、実行スタックにいくつかのローカル変数が作成されます。メソッドが返されると、ローカルオブジェクトがスタックから削除され、一時オブジェクトが割り当てられていた場合は、とにかくガベージ コレクションが行われます。
私の観点からすると、これは別のスレッドで同じ単一インスタンスのメソッドを呼び出すことと変わりません。では、なぜコンテナは Bean の多数のインスタンスをプールするのではなく、1 つの Bean インスタンスを使用できないのでしょうか?
解決
プーリングはいくつかのことを行います。
1 つは、インスタンスごとに 1 つの Bean を持つことで、スレッド セーフであることが保証されます (たとえば、サーブレットはスレッド セーフではありません)。
2 つ目は、Bean の潜在的な起動時間を短縮することです。セッション Bean は「ステートレス」ですが、クライアントに関してのみステートレスである必要があります。たとえば、EJB では、複数のサーバー リソースをセッション Bean に注入できます。その状態は Bean にとってプライベートなものですが、呼び出しごとにその状態を保持できない理由はありません。したがって、Bean をプールすることにより、これらの検索が Bean の作成時にのみ発生するように削減されます。
3 つ目は、トラフィックを調整する手段として Bean プールを使用できることです。プール内に 10 個の Bean しかない場合、同時に動作するリクエストは最大 10 個だけになり、残りはキューに入れられます。
他のヒント
プーリングによりパフォーマンスが向上します。
すべてのリクエスト/スレッドを単一のインスタンスで処理すると、多くの競合とブロックが発生します。
どのインスタンスが使用されるかわからないため (また、複数のスレッドが 1 つのインスタンスを同時に使用する可能性があるため)、Bean はスレッドセーフである必要があります。
コンテナーは、実際のアクティビティに基づいてプール サイズを管理できます。
Java EE モデルのトランザクション性は、スレッド コンテキストを使用してトランザクションのライフサイクルを管理します。
この簡略化により、UserTransaction オブジェクトと直接対話するための特定のインターフェイスを実装する必要がなくなります。トランザクションが InitialContext から取得される (またはセッション Bean に注入される) と、トランザクションは再利用のためにスレッドローカル変数にバインドされます (たとえば、ステートレス セッション Bean のメソッドが、注入されたトランザクションを使用する別のステートレス セッション Bean を呼び出す場合など)。 )
ステートレス セッション Bean のライフ サイクルは、存在しない、パッシブ、および MethodReady (パッシブまたは非アクティブ) 状態です。パフォーマンスを最適化するために、作成状態からメソッド準備完了状態まで Bean をすべて横断するのではなく、コンテナはアクティブ状態とパッシブ状態の間で Bean を管理します。コンテナーのコールバック - ejbActivate() および ejbPassivate() は、Bean プールを管理することによって行われます。
スリーナッツ
メソッドは本質的にスレッドセーフです (静的を含む)。なぜ?メソッド内のすべての変数はスタック メモリ内に作成されるため、シンプルです。メソッド内で使用されるすべての変数は呼び出しごとに作成されます (共有されません)。ただし、パラメーターはスタックの一部ではありません。
ただし、安全でない変数を使用するメソッドは安全ではありません。
a) 静的フィールドまたは変数を呼び出す。ただし、それはあらゆるケースで起こります。
b) 共有されているリソースを呼び出します。EntityManager など。
c) 安全ではないパラメータを渡す。