SingleThreadModelは非推奨であり、スレッドセーフを保証しません。サーブレットでスレッドセーフを保証するための最良の解決/設計アプローチは何ですか?

バクテリア

いずれかのスレッドセーフを保証したいServletSingleThreadModelは非推奨であり、スレッドの安全性を保証するものではありません。その代わりに、synchronized内のブロックを使用できますServlet

サーブレットでスレッドセーフを保証する別の方法はありますか?

はいの場合、どうすればそれを達成できるか説明してください。

いいえの場合、スレッドセーフを保証するための私の設計アプローチはServlet何ですか?

クリストファーシュルツ

Javaサーブレットには、スレッドの問題の影響を受けやすいという特別なことは何もありませんが、一般にWebサーバーのマルチスレッドの性質により、Javaサーブレットで発生する可能性のあるスレッドの問題はすぐに明らかになります

Javaサーブレットは特別ではないという点を強調したいので、上記のことだけを言っていますスレッドセーフではないコードは簡単に記述できます。Javaサーブレットでそれを回避するのははるかに困難です。

:アプリケーションを構築するための一つの一般的な技術は、3つの山の中に(論理的および物理的に)あなたのコードを分離することであるm個のodel(データ)、VのIEW(UI)、およびC -通常は「MVC」と略記ontroller。これを行うとき、「ビュー」と「コントローラー」はステートレスであると見なしますつまり、モデルにはプログラム/ユーザー/トランザクション/その他のすべての状態が含まれ、コントローラーとビューは必要に応じてその状態を変更し、そのモデルがコードを通過できるようにします。

サーブレットコンテナでは、サーブレット自体がコントローラ(またはビュー)のいずれかであり、ステートレスである必要があります。これは非常に簡単です。ユーザー固有またはトランザクション固有のものを含むクラスメンバーを使用しないでください。サーブレットクラスのメンバーは、それ自体がスレッドセーフであるConcurrentMap(のように)、スレッドセーフな方法で使用される必要があります(たとえばsynchronized、へのアクセスをブロックするHashMap)。スレッドセーフなコレクション(例ConcurrentMapでさえ、次のようにスレッドセーフではない方法で使用できることに注意してください。

ConcurrentMap cm = ...;
if(!cm.containsKey("foo")) {
    cm.put("foo", createFoo());
}

上記のコードは、2つのスレッドがの呼び出しを防ぐことはできませんcreateFoo。これは、コストのかかる(または破壊的な!)操作になる可能性があります。2つのスレッド間の競合状態を回避するには、同期ブロックを使用する必要があります

それで、あなたはモデルをどこに置きますか?さて、これにはいくつかのオプションがあります。最も簡単な方法の1つは、すべてをユーザーのに保持することsessionです。セッションはユーザー固有の構造でありHttpServletRequestすべてのオブジェクトから利用できるため、サーブレットはいつでも利用できます。ただし、これは、ユーザーが実際にアプリケーションにログインした場合にのみ機能します。今のところ、ユーザーがいて、ユーザーが独自のセッションを持っていると仮定しましょう。

セッションは、リクエストを行ったユーザーのIDに基づいて、リクエストに自動的に関連付けられます。必要なその他のデータは、リクエスト自体から取得する必要があります(クエリ文字列から取得するリクエストパラメータなど)。

好きなものをセッションに入れることができます。「ビジネスオブジェクト」(特定のアプリケーションで概念を表すために使用するもの)を記述するカスタムクラスMapは、他Mapのs、Listssなど名前付きコレクションを含むオブジェクトよりも望ましいです。他に何も使用せずに構築された完全なWebアプリケーションを見てきました。標準のJavaライブラリクラスであり、それらはマップルックアップとマジックリストインデックスの混乱です。その罠にはまらないでください。独自のクラスを作成してください。

ユーザーモデルデータのもう1つのオプションは、ある種のデータベースにデータを保存することです。単純なファイルストアからリレーショナルデータベース、ドキュメント/列/インデックスストアまで、「データベース」には多くのオプションがあります。それらはすべて独自の長所と短所を持っています。しかし、それらはデータを保存し、ユーザーモデルデータをデータベースに入れることができます。ユーザーをどのように識別しますか?おそらく、セッションにユーザーIDを保存することによって。(したがって、通常はすべてセッションに戻ります)。また、ユーザーのユーザー名(リクエストから入手可能)を使用して、データベース内のユーザーのデータを検索することもできます。

いずれの場合も、サーブレットのクラスメンバーにユーザーの状態(ワークフローなどを含む)に関する情報を保存しないでくださいこれを回避すると、サーブレットのスレッドセーフについて心配する必要がなくなります。

もう1つの問題は、共有リソースの問題ですこの問題の解決策は、これらの共有リソースをスレッドセーフな方法で使用することを確認することです。これは通常、データベースへの接続プール、メッセージキュー、検索インデックスなどのプールされたリソースを使用して実行できます。これらの問題の解決は通常、共有されているリソースのタイプに非常に固有であるため、より具体的な質問をすることをお勧めします。その段階に達したとき。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ