序文
Javaでのシングルトンデザインパターンは、唯一のクラスはシングルトンパターンを実装することができるようになりますが、それは比較的シンプルなデザインから来たのに、あなたは、Singletonパターンを過小評価することはできませんが、それを達成、最も簡単なものですあなたはピットの多くに遭遇したので、電車の中で、あなたのシートベルトを締めます。
Singletonパターンは、定義されました
シングルトンが原因静的変数にグローバルにユニークなオブジェクト、Javaの静的変数のようなビットが、Singletonパターンを作成するには、静的変数は、プログラムが起動したときに、それは多くの原因となります作成され、一度だけインスタンス化されたプログラムの実行であります資源の浪費、良いシングルトンは、この問題は発生しません。Singletonパターンを適用している開発ツール、スレッドプール、キャッシュ、ログや他のオブジェクトの多くは、彼らが唯一、あなたが複数のインスタンスを作成する場合、そのようなリソースの浪費など、予測できない問題につながる可能性があり、オブジェクトを作成する必要があります結果は矛盾や他の問題に対処します。
単一のアイデアの実現の例
- 静的オブジェクトの例
- コンストラクタの民営化は、コンストラクタの禁止を経由してインスタンスを作成します
- 一意のインスタンスを返す、パブリック静的メソッドを提供します
単一例のメリット
1つのオブジェクトだけ、より少ないメモリコスト、良好な性能(オブジェクトがこのような構成を読み取るように、より多くのリソースを必要とするときに発生する、依存性は、他のオブジェクトを生成するアプリケーションが起動したとき、それはシングルトンオブジェクトから直接製造することができる、永久メモリを聞かせ解決する方法)
(、メモリ内のインスタンスが1つしかない、書き込みファイル操作と同時に、ファイル書き込み操作で同じリソースを避けるために、リソースの複数の割り当てを避けてください
)グローバルアクセスポイントを設定し、共有リソースへのアクセスを最適化するために、システム内(例えば、単一クラスの実施形態の設計、マッピングは、すべてのデータ・テーブルを処理する責任があります)
シングルモードの例
主流の書き込みシングルトンパターンが飢えている、怠惰なモード、ダブルチェックロックモードを、静的な内部クラスのシングルトン、シングルトンモードの列挙クラスは、怠惰なモードは、二つのモードの不適切なロックモードの文言をダブルチェックする5つの方法を実装しますマルチスレッドシングルトンか、異常の一つのケースになります、私たちは詳細にあなたを伝えるために戻ってきます。私たちは、最も基本的なモデルから飢えた男の一つのケースを書いている私たちの道を開始しました。
飢えモード
使用されるモデルを飢え、静的プロパティ、直接インスタンス化オブジェクトの定義が簡単で、粗形態です。コードは以下の通りであります:
//在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
public class SingletonObject1 {
// 利用静态变量来存储唯一实例
private static final SingletonObject1 instance = new SingletonObject1();
// 私有化构造函数
private SingletonObject1(){
// 里面可能有很多操作
}
// 提供公开获取实例接口
public static SingletonObject1 getInstance(){
return instance;
}
}
モードを飢えの長所と短所
利点
- JVMのスレッド安全なレベル、静的なキーワードは、この変数を参照する場合、この変数は書き込み操作のように完了していることを保証するために、
短所
- 私たちは、このクラスをロードするために初期化され、より大きな類推、場合レイジーローディングは、スペースの無駄が生じ、達成することはできませんが、我々は、メモリ空間の浪費につながる、長い時間のためにこのクラスを使用していませんでした。
レイジーモード
怠惰な怠惰なモードと同じように空腹時にのみ、決して空腹防ぐための準備ができて食べ物の前に、彼の胃を埋めるために何かを見つけようとします。レイジーモードは、クラスを初期化するために使用した場合達成するためにモードを飢えに起因する無駄なスペースの問題を解決するために、遅延ロードを実装するだけでなく、他の問題を紹介し、のはこの怠惰なモードを見てみましょう
public class SingletonObject2 {
// 定义静态变量时,未初始化实例
private static SingletonObject2 instance;
// 私有化构造函数
private SingletonObject2(){
}
public static SingletonObject2 getInstance(){
// 使用时,先判断实例是否为空,如果实例为空,则实例化对象
if (instance == null)
instance = new SingletonObject2();
return instance;
}
}
このレイジー・モードの実装コードの上には、マルチスレッドと誰もがより多くの理由について話をするために、オブジェクトがインスタンス化されるときの主要な問題が発生し、シングルトンであることを保証することはできませんので、一人で私が提案したコードをインスタンス化する場合でスレッドが複数のインスタンスを初期化する場合があります。
1 if (instance == null)
2 instance = new SingletonObject2();
我々はすべてのリソースの保護措置を持っていないので、1位に2つのスレッドがあると仮定し、その二つのスレッドの判断がinstance
空になって、2を実行するコードの例があるので、状況は、複数のインスタンスが存在します。
我々はすでに我々は、リソースをロックした場合、複数のインスタンスの問題を解決することはできないが、資源のない保護がないため、上記のコードは、複数のインスタンスを表示されていることを知っていますか?確かに、私たちは与えるgetInstance()
方法は、追加synchronized
のキーワードgetInstance()
メソッドが保護されたリソースは、複数のインスタンスの問題を解決することができるようになりますとなりましたが。プラスsynchronized
、次のようにキーコードの後、次のとおりです。
public class SingletonObject3 {
private static SingletonObject3 instance;
private SingletonObject3(){
}
public synchronized static SingletonObject3 getInstance(){
/**
* 添加class类锁,影响了性能,加锁之后将代码进行了串行化,
* 我们的代码块绝大部分是读操作,在读操作的情况下,代码线程是安全的
*
*/
if (instance == null)
instance = new SingletonObject3();
return instance;
}
}
これは本当に状況は、複数のインスタンスを発生することがあり解決が、追加synchronized
システムのパフォーマンスが低下、コードのシリアル化をロックした後、キーワードの後に、新たな問題を導入します。getInstance()
操作のほとんどの方法が読み取り操作され、読み出し動作は、スレッドセーフです。
レイジー・モードの長所と短所
利点
- これは、メモリ空間を節約し、遅延ロードを実装します
短所
- ロック解除され、スレッドセーフの場合には、複数のインスタンスが発生する可能性が
- システムに重大なパフォーマンスの問題があるように、ロックされた場合には、プログラムは、シリアライズされます
ダブルチェックロックモード
レイジー・モードでは、我々はことを知っているgetInstance()
操作方法のほとんどが読み込まれ、読み出し動作がために、スレッドセーフであるgetInstance()
ロックする方法、それによって両方をロックするよりエレガントな方法を作成し、パフォーマンスの問題の多くを引き起こしましたすることができgetInstance()
ますが、パフォーマンスを犠牲にすることなくロックし、このモデルでは、私たちが今知っているものであるロックモードをダブルチェックするために、我々はダブルチェックロックモードを達成するために、単一のケースを見てみましょう:
public class SingletonObject4 {
private static SingletonObject4 instance;
private SingletonObject4(){
}
public static SingletonObject4 getInstance(){
// 第一次判断,如果这里为空,不进入抢锁阶段,直接返回实例
if (instance == null)
synchronized (SingletonObject4.class){
// 抢到锁之后再次判断是否为空
if (instance == null){
instance = new SingletonObject4();
}
}
return instance;
}
}
ロックモードをチェックダブルが言うことができる上記を達成するために、シングルモード、シングルの場合は解決し、パフォーマンス、スレッドの安全性の問題を達成するために非常に良い例である、マルチスレッドの場合には、可能完璧に見えますが、上記のコードの実現あるだろうNULLポインタの問題は、のは、nullポインタ問題がある理由を理解するために協力しましょう。
我々は次のコードを見て、多分あなたは理解していない、コードを最適化するために、仮想機会内部のオブジェクトをインスタンス化する際に問題が発生し、並べ替え、NULLポインタの仮想マシンの最適化と命令によるものです
private SingletonObject4(){
1 int x = 10;
2 int y = 30;
3 Object o = new Object();
}
JVMがインスタンス化されるSingletonObject4()
1、2実行のために必須ではないが、それは3,1,2であってもよい、JVM最適化され、それは2,3,1であってもよい、JVMは、最終的に完成インスタンス化を確実にします。コンストラクタ作業効率を向上させるためには、比較的長い場合、JVMは、オブジェクトが完了したコンストラクタ関数の属性をインスタンス化されて返されます。これはまた、nullポインタ例外が発生します、財産の使用には、プロパティが完了し、インスタンス化されないことがあり、インスタンスを取得するために、他のスレッドが生じました。
上記のダブルチェックロックモードの問題に起因nullポインタ例外を解決するには、使用する必要があるvolatile
キーワードを、volatile
キーワードは、厳密に従うhappens-before
読み出し動作の前に、操作を完了しなければならない書くという原則を。追加volatile
のキーワード以下のシングルトンパターンコードを:
// 添加volatile关键字
private static volatile SingletonObject5 instance;
private SingletonObject5(){
}
public static SingletonObject5 getInstance(){
if (instance == null)
synchronized (SingletonObject5.class){
if (instance == null){
instance = new SingletonObject5();
}
}
return instance;
}
}
追加volatile
キーワードは、シングルモードを達成するための良い例です後に問題がないだろうマルチスレッドパフォーマンスの場合にはセキュリティスレッドを確保するために、ロックモードを確認してくださいダブル。
内部の静的タイプシングルトン
内部スタティック型単実施の形態は、シングルモードの実施形態ホルダーと呼ばれ、内部クラスのインスタンスが作成され、外部のJVMクラスのローディングは、静的内部クラスをロードされていないので、唯一の内部クラスのプロパティ/メソッドが呼び出されこれは、ロードされ、静的プロパティが初期化されます。静的プロパティは、static
一度だけインスタンス化され、かつ厳密にインスタンス化の順序を保証することを確認するように変更します。内部スタティック型シングルトンパターンコードは次の通りであります:
public class SingletonObject6 {
private SingletonObject6(){
}
// 单例持有者
private static class InstanceHolder{
private final static SingletonObject6 instance = new SingletonObject6();
}
//
public static SingletonObject6 getInstance(){
// 调用内部类属性
return InstanceHolder.instance;
}
}
内部の静的型シングルトンパターンは、実現の良好な単実施の形態である、一般的に、シングルモードの実施例を達成するために使用されます。任意の添加ロックの非存在下でマルチスレッドの安全性を確保するために、任意のパフォーマンスへの影響や空間を無駄にしませんでした。
例シングルモードの列挙クラス
列挙型クラスはシングルトンパターンが強く、単一のケースを達成するためのモードをお勧め効果的なJavaの作者である、列挙型は、スレッドセーフで、一度だけロードされた実装、Singletonパターンを達成するために、この機能のデザイナーフルに活用、列挙非常にシンプルな言葉遣い、列挙型およびシングルモードの実施例だけで破損していない達成して単一の実施形態で実装されています。
public class SingletonObject7 {
private SingletonObject7(){
}
/**
* 枚举类型是线程安全的,并且只会装载一次
*/
private enum Singleton{
INSTANCE;
private final SingletonObject7 instance;
Singleton(){
instance = new SingletonObject7();
}
private SingletonObject7 getInstance(){
return instance;
}
}
public static SingletonObject7 getInstance(){
return Singleton.INSTANCE.getInstance();
}
}
シングルトンとソリューションを破壊するための方法
我々は、単一の実施形態の破壊を防止したい場合、Ruoyi、コンストラクタに決定することができるので、1は、列挙に加えて、他の方法は、単一の反射の仕方によって破壊される、反射は、コンストラクタを呼び出すことにより、新しいオブジェクトを生成しましたインスタンスは、次のように解決策がある、新しいインスタンスの生成を防ぐため、あります。
private SingletonObject1(){
if (instance !=null){
throw new RuntimeException("实例已经存在,请通过 getInstance()方法获取");
}
}
図2に示すように、シングルトンクラスは、直列化シリアルインターフェイスを実装する場合、単一の実施形態をデシリアライズすることによって破壊することができるので、インターフェースのシリアル化を実装する必要がある場合、我々はシリアライゼーションインタフェースを実装することができない、デシリアライズは、)(readResolveメソッドを書き換えることができます。直接関係シングルトンオブジェクトの直列化復元を返されました。
public Object readResolve() throws ObjectStreamException {
return instance;
}
遂に
一緒に進歩「技術的ボーエンのフラットヘッドの兄」:少し宣伝を再生する、マイクロチャンネルスキャンコード番号の公衆に焦点を歓迎しました。