一般的なシングルトンデザインパターン(シングルトン)

Singletonパターン(シングルトン)

シングルトンオブジェクト(シングルトン)は、共通のデザインパターンです。Javaアプリケーションでは、シングルトンは、JVMを保証することができ、オブジェクトのインスタンスは1つだけ存在します。このモデルは、いくつかの利点があります。

  1. いくつかのクラスには、多くのオーバーヘッドがあるいくつかの大規模なオブジェクトのために、より頻繁に作成されます。
  2. システムメモリの使用頻度を減らし、new演算子を排除、ストレスGCを減らします。
  3. こうした交流の中核取引エンジンなどのいくつかのクラス、クラスは複数の単語を作成することができれば、トランザクション処理を制御、システムが完全に混沌としています。(例えば、より多くの同時コマンドへの軍事司令官より、となります間違いなく混乱があった)、これだけ全体のプロセスのコアトランザクションサーバを独立に制御することを確実にするためには、シングル・ケース・モデルを使用。

まず、簡単なシングルトンクラスを記述します。

public class Singleton {
	/* 持有私有静态实例,防止被引用,此处赋值为 null,目的是实现延迟加载 */
	private static Singleton instance = null;
	
	/* 私有构造方法,防止被实例化 */
	private Singleton() {
	}
	
	/* 静态工程方法,创建实例 */
	public static Singleton getInstance() {
		if (instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

どのスレッドセーフ保護クラスが存在しないように、我々はマルチスレッド環境でそれを置く場合は、このクラスは、基本的な要件を満たしていますが、確かに問題があるでしょう、どのように解決するには?次のように私たちはまず、synchronizedキーワードgetInstanceメソッドを追加することを考えます:

public static synchronized Singleton getInstance() {
	if (instance == null) {
		instance = new Singleton();
	}
	return instance;
}

各呼び出ししかし、synchronizedキーワードがロックされているオブジェクト、このような使用は、パフォーマンスは、低下する
のgetInstance()は、オブジェクトをロックする必要があります実際には、最初に作成されたオブジェクトあなたがロックする必要がある場合、その後、あなたが必要としないので、この場所は改善する必要があります。私たちは、次のように変更しました:

public static Singleton getInstance() {
	if (instance == null) {
		synchronized (instance) {
			if (instance == null) {
				instance = new Singleton();
			}
		}
	}
	return instance;
}

問題は、前述の解決には思われる、ロックされたときに、唯一のインスタンスがnullの呼び出しが必要とされていない場合に言うと、唯一のロックに必要なオブジェクトを作成することで内部に加え、synchronizedキーワード、パフォーマンスいくつかの改善。しかし、このような状況は、まだ次のような場合を参照してください、問題がある可能性があります:オブジェクトを作成し、割り当て操作は、Java命令、そのインスタンス=新しいシングルトン()で別々に行われ、文は二つのステップで実行されます。しかし、JVMが新しいJVMインスタンスシングルトンがあるかもしれないことをその手段は、これらの2つの操作の順序を保証するものではありませんシングルトンインスタンスを初期化するために行く、その後、その後、直接割り当てられたインスタンスメンバー、スペースを割り当てます。これは間違っている可能性があり、我々はA、Bに例えば二つのスレッドを、持っています:

  1. 最初かどうかを決定するに、Bスレッド
  2. 最初のインスタンスがヌルであるため、それはインスタンスを実行し、同期ブロックに入る=新しいシングルトン()。
  3. 内部JVMの最適化メカニズムので、JVMは、まずシングルトンインスタンスに割り当てられたいくつかのブランクのメモリを描く、およびインスタンスメンバー(この時点でJVMインスタンスを初期化するために開始しないことに注意してください)に割り当てられ、その後A同期ブロックを残しました。
  4. この時間インスタンスがnullでないのでBは、同期ブロックに入り、それは直ちに同期ブロックを左および方法と呼ばれることプログラムに結果を返します。
  5. この時点で、Bのスレッドは、それが初期化されていないので、エラーが発生したことを見つけるために、シングルトンインスタンスを使用する予定。プログラムがまだ可能性のあるエラーであるので、実際には、プログラムの動作中に非常に挑戦的な、マルチスレッド環境で特に書き込み処理でより多くの困難、我々が見ることができる。この時点から、複雑になっています。我々はさらに、プログラムを最適化:
private static class SingletonFactory{
	private static Singleton instance = new Singleton();
}

public static Singleton getInstance(){
	return SingletonFactory.instance;
}

実際には、内部クラスシングルトンクラスがロードされたとき、このクラスのロード処理が相互に排他的スレッドであることを確実にするために単一の実施形態、JVM内部機構を維持するために実装されています。だから我々は最初のgetInstanceを呼び出すときに、JVMは、そのインスタンスを確実に私たちを助けることができることを一度だけ作成され、我々は上記の問題を心配しないように、インスタンスに割り当てられたメモリは、初期化されていることを確認します。一方、また、最初の呼び出しの際に相互排他メカニズムを使用する方法は、これは低パフォーマンスの問題を解決します。
私たちは、Singletonパターンの完璧な要約を行うよう:

public class Singleton {

	/* 私有构造方法,防止被实例化 */
	private Singleton() {
	}
	
	/* 此处使用一个内部类来维护单例 */
	private static class SingletonFactory {
		private static Singleton instance = new Singleton();
	}
	
	/* 获取实例 */
	public static Singleton getInstance() {
		return SingletonFactory.instance;
	}
}

例外がコンストラクタでスローされた場合、実際には、それは、必ずしも、完璧、インスタンスが作成されることはありません、間違っていることでしょう。だから、何かが非常に完璧ではない、我々は唯一の実際の状況に応じてすることができ、最も適切な実装シナリオを選択します。それは、この実現した:我々は唯一の同期化する必要があるため、限り作成とのgetInstance(など)別のアドオン同期キーワードを作成するために、一度に別のクラスを作成するには、ことも可能です。

public class SingletonTest {

	private static SingletonTest instance = null;
	
	private SingletonTest() {
	}
	
	private static synchronized void syncInit() {
		if (instance == null) {
			instance = new SingletonTest();
		}
	}
	
	public static SingletonTest getInstance() {
		if (instance == null) {
			syncInit();
		}
		return instance;
	}
}

パフォーマンスが影響されないようにパフォーマンスを実現するには、プログラム全体は、インスタンス一度作成しました。
シングルトンの研究を通して教えてくれる:

  1. シングルトンシンプルは理解するが、それはまだいくつかの特定の実装の難しさを持っています。
  2. synchronizedキーワードロックは、使用中、必ず使用に適切な場所で(ロックオブジェクトおよび手順を使用する必要性への配慮、時には全体ではなく、オブジェクトやプロセス全体をロックする必要があります)する際に、オブジェクトです。

ここでは、シングルトンは、基本的には、完成されている最後に、私は突然、別の問題を考え、実現可能また、シングルトンの効果を達成するために、静的なクラスメソッドを使用することで、両方のここでの違いは何ですか?
まず、静的クラスがインタフェースを実装することはできません。(クラスからのものであると言ったが、静的メソッドは変更を許可しないインターフェイスは、あっても、非静的場合に達成されているので、それはスタティックを破壊することができる)
次に、単一の実施形態は、一般的に初期静的クラスを遅延させることができます最初の初期化に最初にロードされます。いくつかのクラスの比較的大きな理由は、遅延ロードヘルプので、負荷の遅延は、パフォーマンスを向上させる理由。
ここでも、シングルトンクラスを継承することができ、彼の方法をオーバーライドすることができます。しかし、内部の静的クラスメソッドは静的であり、かつ、上書きすることはできません。
最後に、より柔軟なシングルトンクラスは、すべての後に、普通のJavaクラスの実現から、限り、単一の例の基本的なニーズとして、あなたは、任意の内部のいくつかの他の機能を達成するため、非静的クラスすることができます。
これらの一般化の上、2の基本的な違いを見ることができる、しかし、一方で、私たち以上のSingletonパターンの最終的な実現は、内部が実装する静的クラスを使用することであるので、2つは非常にあるから、協会が、我々は専門用語でレベル差の問題を検討します。、HashMapのは同じ赤黒木を達成するためのリンクリストの配列+ +を使用して、実際には、さまざまな方法で単一の問題に対処するために、生活の中でたくさんのこと完璧なソリューションを作成するには、2つのアイデアを組み合わせ、ある、常に存在しています長所と短所は、最も完璧な方法は、問題を解決する最善のために、各方法の長所を組み合わせることです!

リリース7件のオリジナルの記事 ウォンの賞賛2 ビュー148

おすすめ

転載: blog.csdn.net/lixin_nobody/article/details/104920796