シングルケースパターン: は、一般的に使用されるソフトウェア設計パターンであり、そのコア構造にはシングルトンと呼ばれる特別なクラスが含まれています。クラスにはインスタンスが 1 つだけあります。つまり、クラスにはオブジェクト インスタンスが 1 つだけあります。
システム内の一部のクラスでは、重要なインスタンスは 1 つだけです。たとえば、システム内に複数の印刷タスクが存在する可能性がありますが、チケットを販売する場合は、合計 100 個のチケットが存在する可能性があります。チケットを同時に販売する窓口は複数ありますが、オーバーブッキングにならないように注意する必要があります (ここでの残りのチケット数はシングルトンであり、チケット販売にはマルチスレッドが含まれます)。ウィンドウ オブジェクトを一意化するメカニズムが使用されていない場合、複数のウィンドウがポップアップし、これらのウィンドウがすべて同じ内容を表示すると、繰り返し作成するとリソースが無駄になります。
アプリケーションシナリオ (出典:「Dahua Design Pattern」):
要件: フロントエンドにツールボックスウィンドウを作成します。ツールボックスは表示されないか、1 つだけ表示されます
問題が発生しました: 毎回メニューをクリックすると、「ツールボックスの作成」ウィンドウが繰り返されます。
解決策 1: オブジェクトを作成するたびに、まず if ステートメントを使用して null であるかどうかを判断し、null である場合は、オブジェクトを再度作成します。
要件: 5 か所でツールボックス フォームをインスタンス化する必要がある場合
発生した問題: この小さなバグは 5 か所で修正する必要があり、コードが繰り返され、コード使用率が低いです
解決策 2: を使用しますシングルトン モードでは、クラスのインスタンスが 1 つだけ存在することを確認し、そのインスタンスへのグローバル アクセス ポイントを提供します。
シングルトンモードはレイジースタイルとハングリースタイルに分けられます:
レイジーシングルトンモード: クラスロード時に初期化なし。
ハングリースタイルシングルトンモード: クラスのロード時に初期化が完了するため、クラスのロードは遅くなりますが、オブジェクトの取得速度は高速です。
最初のタイプ(怠惰なやつ、スレッドが安全ではない):
public class SingletonDemo1 {private static SingletonDemo1 instance;private SingletonDemo1(){}public static SingletonDemo1 getInstance(){if (instance == null) { instance = new SingletonDemo1(); }return instance; } }
この遅延読み込みの書き方は明白ですが、致命的なのは複数のスレッドで適切に動作しないことです。
2 番目のタイプ (怠け者、スレッドセーフ):
public class SingletonDemo2 {private static SingletonDemo2 instance;private SingletonDemo2(){}public static synchronized SingletonDemo2 getInstance(){if (instance == null) { instance = new SingletonDemo2(); }return instance; } }
この書き方では、getInstance() メソッドに同期ロックを追加します。これは複数のスレッドでうまく動作し、遅延読み込みも優れているように見えますが、(ロックのため) 非常に非効率で、ほとんどの場合同期は必要ありません。
3 番目のタイプ (ハングリーマン):
public class SingletonDemo3 {private static SingletonDemo3 instance = new SingletonDemo3();private SingletonDemo3(){}public static SingletonDemo3 getInstance(){return instance; } }
このメソッドは、classloder メカニズムに基づいてマルチスレッド同期の問題を回避します。ただし、クラスがロードされるときにインスタンスがインスタンス化されることは明らかです。この時点でインスタンスを初期化すると、遅延読み込みの効果が得られます。
4 番目の方法 (hungry中国語、バリアント):
public class SingletonDemo4 {private static SingletonDemo4 instance = null;static{ instance = new SingletonDemo4(); }private SingletonDemo4(){}public static SingletonDemo4 getInstance(){return instance; } }
表面的にはかなり異なるように見えますが、実際には 3 番目の方法はほぼ同じで、どちらもクラスの初期化中にインスタンス化されます。
5 番目のメソッド (静的内部クラス):
public class SingletonDemo5 {private static class SingletonHolder{private static final SingletonDemo5 instance = new SingletonDemo5(); }private SingletonDemo5(){}public static final SingletonDemo5 getInsatance(){return SingletonHolder.instance; } }
このメソッドも、インスタンスの初期化時にスレッドが 1 つだけであることを保証するためにクラスローダー メカニズムを使用します。これは、3 番目および 4 番目とは異なります。はい (非常に微妙な違い): 3 番目と 4 番目のメソッドは、Singleton クラスがロードされている限り、インスタンスはインスタンス化されます (遅延ロード効果は達成されません)。このメソッドは、Singleton クラスがロードされるというものです。 , インスタンスは必ずしも初期化されているわけではありません。 SingletonHolder クラスはアクティブに使用されないため、getInstance メソッドを呼び出してインスタンスをインスタンス化することによってのみ明示的にロードされます。インスタンスのインスタンス化がリソースを消費するため、インスタンスを遅延ロードしたい場合を想像してください。一方、Singleton クラスが他のクラスでアクティブに使用されるかどうかを確認できないため、Singleton クラスのロード時にインスタンス化したくない場合を考えてください。 places.がロードされている場合、現時点でインスタンスをインスタンス化するのは明らかに不適切です。現時点では、この方法は 3 番目や 4 番目の方法よりも合理的であると思われます。
6 番目 (列挙):
public enum SingletonDemo6 { instance;public void whateverMethod(){ } }
このメソッドは、Effective Java の作者である Josh Bloch によって提唱されています。これは、マルチスレッド同期の問題を回避するだけでなく、新しいオブジェクトのシリアル化解除や再作成も防ぎます。しかし、個人的には、enum 機能は 1.5 で追加されたばかりなので、実際の仕事ではこのように書く人をほとんど見かけません。
7番目のタイプ(二重認証ロック):
public class SingletonDemo7 {private volatile static SingletonDemo7 singletonDemo7;private SingletonDemo7(){}public static SingletonDemo7 getSingletonDemo7(){if (singletonDemo7 == null) {synchronized (SingletonDemo7.class) {if (singletonDemo7 == null) { singletonDemo7 = new SingletonDemo7(); } } }return singletonDemo7; } }
これは、一般にダブルチェック ロックとして知られる 2 番目の方法のアップグレード バージョンです。詳細な紹介については、次を参照してください。
JDK1.5 以降では、ダブルチェック ロックは通常どおりシングルトン効果を実現できます。
マルチスレッドのシングルケース マルチスレッドプログラムでは、複数のスレッドが同時にシングルトンにアクセスする場合、複数のインスタンスを作成することができます。このとき「ロック」でロックする必要があります。ロック、デッドロック、およびロック間の通信については、後で詳しく説明します。
参考:
以上がシングルトンモードの共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。