INSTANCE ホルダー クラスを使用してシングルトン パターンを実装する場合、コンパイラは classname$1.class という名前の別のクラス ファイルを生成します。このリンクで質問を見つけることができます: here . だから私の質問は、シングルトンパターンの解決策は何ですか? ダブルチェック?
4 に答える
このシングルトン コードがスレッド セーフな初期化を実装する方法を尋ねているようです。
public final class Test {
static final class TestHolder {
private static final Test INSTANCE = new Test();
}
private Test() {}
public static Test getInstance() {
return TestHolder.INSTANCE;
}
}
次の理由により、ソリューションのスレッド セーフが保証されます。
- 静的初期化はスレッドセーフな方法で実行され、
- 一度初期化すると、
final
それ以上同期しなくても変数を使用できます。
ダブルチェックロックを行っていません。
この特定のパターンは、スレッドセーフかつ遅延初期化されていることに注意してください。非遅延初期化でスレッドセーフなシングルトンが必要な場合は、次のようにします。
public final class Test {
private static final Test INSTANCE = new Test();
private Test() {}
public static Test getInstance() {
return INSTANCE;
}
}
「enum
シングルトンとして」のアプローチも受け入れられます...エンジニアのドレリーが言っていることにもかかわらず。
ダブルチェック ロックを使用した遅延初期化は、Java 5 以降 ( a を使用して正しく実行した場合volatile
) から正しく実装できますが、Java 1.4.x 以前ではイディオムが壊れています。
単純な列挙を使用できます。
public enum Singleton {
INSTANCE;
}
メソッドを呼び出すのではなく、INSTANCE
単純に as にアクセスできます。また、デフォルトでは、Enum インスタンスの作成はスレッドセーフです。Singleton.INSTANCE
getInstance()
展開アーキテクチャによっては、Java でシングルトンを実装することが非常に難しくなる場合があります。シングルトンについて話しているときは、そのスコープ/コンテキストについても話さなければなりません。このシングルトンはしばしば悪と呼ばれ、アンチパターンと見なされてきたことを理解している人はほとんどいないためです。
アプリケーションサーバーの外部にある単一の jvm にデプロイする場合、慣用的なアプローチは、クラスのプライベート最終静的インスタンスをそれ自体に実装し、適切な名前のメソッド (getInstance() が一般的) を介してこれを公開し、makeクラス private のコンストラクター。これは、単一のクラスローダーと単一の jvm に制約されたシングルトンです。
ただし、この状況は非常にまれです。
他のすべての状況では、クラスローダーの問題と、コードを複数の jvm/server にデプロイする問題を考慮する必要があります。典型的な Java EE アプリケーション コンテナーでは、通常、各 war は独自のクラスローダーを使用してロードされます。各 war がシングルトンを含む jar に依存している場合、それぞれがそのシングルトンの独自のコピーを取得します。シングルトンがたとえばDB接続用であり、それらの多くが許可されている場合、これは問題ありません。ただし、シングルトンが限られたリソースへのアクセスを保護することになっている場合、webapp ごとにそのリソースにアクセスできるクラスが 1 つあるため、これはうまく機能しません。ここでのシングルトンのスコープはコンテナ スコープです。
クラスターとライブ フェイルオーバーを備えた完全なエンタープライズ展開では、さらに悪化します。この環境では、ソフトウェアの多数のコピーが同時に実行されています。このスコープ (エンタープライズ スコープ) で動作する Java のみのシングルトンを想像するのは困難です。このレベルでは、シングルトンの作成または実行 (複数のインスタンスを使用しても問題ないが、一度にリクエストを処理できるのはそのうちの 1 つだけの場合) のための唯一の信頼できる情報源と、作成するすべてのシングルトンの情報を把握する必要があります。同じタイプは、唯一の信頼できる情報源であるエンタープライズ セマフォに従う必要があります。
jdk 1.5以降はenumを使用します。詳細については、htis リンクを確認してください。
- ロックの再確認はお勧めしません。パフォーマンスが向上しません。
- あなたが言及したリンクの解決策は、同期を使用せず、遅延読み込みを使用するため、静的内部クラスを使用した効率的な解決策ですが、列挙型はパフォーマンスとともに実装するのが最も簡単です。
以下の記事では、ダブル チェック ロックが不適切な選択である理由を説明しています[トーマスが指摘したように、以下の記事で言及されているダブル チェック ロックの問題は Java 1.5 で修正されました]: http://www.ibm.com/developerworks/java/library/ j-dcl/index.html