まず、単語の背景
同社はプリンタを持っている場合、我々はそれを使用したいが、彼は時折、自宅で購入しながら、文書を印刷する必要がないという理由だけで、このプリンタは、単一の例として、次のように表示することができ、もちろん、彼を家に持って来ることができませんでした分析します
シナリオの第二に、使用
あなたは、システムリソースを節約するために、インスタンスの数を制御したいとき。
第三に、モデル解析
同社のプリンタ:シングルトンオブジェクト
オブジェクトの新しいインスタンス:自分の家のプリンタを購入します
第四に、コード分析
1.怠惰なタイプ、スレッドセーフ
遅延初期化されている:あります
マルチスレッドセーフである:なし
難易度を実現:簡単
説明:これは、最大の問題は、マルチスレッドをサポートしていません実現し、実装の最も基本的な方法です。同期一切ロックが存在しないので、それほど厳密にそれを言えば、シングルトンではありません。
明らかに、このよう遅延ロードは、スレッドセーフ必要としない、それが適切にマルチスレッドで動作することはできません。
/ ** * 1、遅延型、スレッドセーフ * / パブリック クラスSingletonOne { プライベート 静的SingletonOneインスタンス; プライベートSingletonOne(){ } // 全く同期がロックしていない パブリック 静的SingletonOneのgetInstanceを(){ IF(例えば== NULL ){ インスタンス = 新しい新しいSingletonOne(); } 戻りインスタンス; } }
2、怠惰なスタイル、スレッドセーフ
遅延初期化されている:あります
これは、マルチスレッドセーフです:さ
難易度を実現:簡単
説明:この方法で良い遅延ロードを持って、マルチスレッドでうまく機能することができ、しかし、例99%が同期を必要としない、非常に低い効率です。
長所:最初の呼び出しは、メモリの浪費を避けるために、初期化されました。
短所:シングルケースを確実にするために、同期ロックする必要がありますが、ロックは、効率に影響を与えます。
パフォーマンスのgetInstance()アプリケーションが(あまり頻繁に使用している)重要ではありません。
/ ** * 2、遅延型、セキュリティスレッド * / パブリック クラスSingletonTwo { プライベート 静的SingletonTwo例えば、 プライベートSingletonTwo(){ } // ロックに適用される同期方法、外部同期機構が呼に追従するように パブリック 静的 同期のgetInstance SingletonTwo (){ IF(例えば== NULL ){ インスタンス = 新しい新しいSingletonTwo(); } 戻りインスタンス; } }
3、空腹中国風
遅延初期化されている:なし
これは、マルチスレッドセーフです:さ
難易度を実現:簡単
:説明一般的に使用される。このように、しかしがちなゴミオブジェクト。
長所:ロックされていない、効率が向上します。
短所:クラスがメモリを無駄にロードされたときに初期化。
クラスのロードが多くあるの原因があるがしかし、クラスのインスタンスへのインスタンスは、一度にロードされ、シングルトンモードでそれらのほとんどは、getInstanceメソッドを呼び出しているが、それは決定できない、クラスローダのメカニズムは、同期の問題のマルチスレッド化を回避基づいています明らかに、インスタンスの初期化遅延ロードの効果に達しなかった他の方法(または他の静的メソッド)クラスローダをリードは、あります。
/ ** * 3、式飢え * / パブリック クラスSingletonThree { // クラスのオブジェクトがロードされるときに初期化(同期化機構に基づいするクラスローダマルチスレッド、のloadClassクラスローダタイプのロックを回避する) プライベート 静的 SingletonThreeインスタンス= 新しい新しいSingletonThree( ); プライベートSingletonThree(){ } パブリック 静的SingletonThreeのgetInstanceは(){ 戻りインスタンス; } }
図4に示すように、二重ロック検出/ダブルチェックロック(DCL、即ち、ダブルチェックロック)
JDKのバージョン: JDK1.5から
遅延初期化されている:あります
これは、マルチスレッドセーフです:さ
難易度を実現:より複雑に
説明:このデュアルモードロック機構、および安全なマルチスレッドには、高い性能を維持することができます。
パフォーマンスのgetInstance()は、アプリケーションにとって非常に重要です。
/ ** * 4、ダブルロック検出/ダブルチェックロック(DCL、すなわち、チェックインロックダブル) * / パブリック クラスSingletonFour { // このディレクティブは、コンパイラによって最適化されていないことを確認するためのコマンドなどの揮発性の重要な役割、省略、マルチスレッディングはシングルトン複数のローカル電話を防止 プライベート 揮発性 スタティックSingletonFourシングルトン、 プライベートSingletonFour(){ } パブリック 静的SingletonFour getSingletonFour(){ IF(シングルトン== NULL ){ // シングルトンの初期化がロック 同期(SingletonFourを。クラス){ IF(シングルトン== NULL){ シングルトン = 新しいSingletonFour(); } } } 戻りシングルトン。 } }
図5に示すように、レジスタベース/静的内部クラス
遅延初期化されている:あります
これは、マルチスレッドセーフです:さ
難易度を実現:全般
説明:このようにロックモードを確認し、二重同じ効果を得るが、実装が簡単であることができます。遅延を使用して静的フィールドの初期化は、このモードではなく、二重ロック検出モードを使用すべきです。本実施形態では、遅延は、インスタンス・フィールドを初期化するために必要なときに二重ロック検出モードを使用することができる、唯一の静的フィールドに適用されます。
このように同じクラスローダ機構の使用は、初期化インスタンスに1つだけのスレッドが、それは今である第三の方法が異なっていることを確認するため:最初の3つの方法があれば、シングルトンクラスは、インスタンスがインスタンス化されロードされる(遅延ロードに達していません効果)が、このアプローチは、シングルトンクラスをロードされ、インスタンスが初期化されなくてもよいです。SingletonHolderクラスがアクティブに使用されていないので、明示的な呼び出しgetInstanceメソッドによって明示的にインスタンスをインスタンス化するSingletonHolderクラスをロードします。彼らはイニシアチブをするために、他の場所でも使用することができることを保証することはできませんので、想像し、あなたがインスタンスをインスタンス化した場合、リソースを消費するので、それはロードを遅延する場合、他の一方で、クラスはシングルトン、シングルトンクラスインスタンス化される時にロードする必要はありませんロードされ、今回は明らかに不適切なインスタンスを生成します。今回は、方法の最初の3種類に比べて、このように、それは非常に合理的です。
/ ** * 5、レジスタベース/静的内部クラス * / パブリック クラスSingletonFiveは{ / * 民営内部クラス原因: 1. SingletonFiveは民営化オブジェクト生成 インスタンス化インスタンスがリソースを消費するので、それをしたい場合は2を遅延ロードは、 他の一方で、シングルトンのクラスローダでインスタンス化する必要はありません 、彼らはシングルトンクラスは、積極的に他の場所で使用されるようにもロードすることができ、確実にすることはできませんので ので、この時間は、インスタンスが明確に不適切なインスタンス化されるので、行くと初期化を呼び出すために使用され、民営内部クラスを置きます。 * / プライベート 静的 クラスSingletonFiveHolder { プライベート 静的 最終 SingletonFive INSTANCE = 新しい新しいSingletonFive(); } プライベートSingletonFive(){ } パブリック 静的 ファイナルSingletonFiveのgetInstance(){ 戻りSingletonFiveHolder.INSTANCEと、 } }
6、列挙
JDKのバージョン: JDK1.5から
遅延初期化されている:なし
これは、マルチスレッドセーフです:さ
難易度を実現:簡単
説明:この実装は、広く採用されていないが、これは、シングルモードの実施例を実現するための最良の方法です。これは、絶対の複数のインスタンスを防止するために、自動サポートシリアル化メカニズムよりコンパクトです。
このアプローチは、それがマルチスレッド同期の問題を避けることができるだけでなく、効果的なJavaの作成者ジョシュ・ブロッホ方法を提唱するだけでなく、自動的に、デシリアライゼーションは絶対に複数のインスタンス化を防ぐため、新しいオブジェクトを再作成しないようにする直列化メカニズムをサポートしています。しかし、JDK1.5には、このように書くの後だけ助けるが、奇妙に感じることができない列挙型のプロパティに入社し、実際には、ほとんど使用されません。
反射攻撃によってプライベートコンストラクタを呼び出しません。
/ ** * 6、列挙 * / パブリック 列挙SingletonSix { // インスタンスが実際SingletonSixインスタンス= SingletonSix.INSTANCE、列挙オブジェクトを表しますに呼び出すことができ INSTANCE; 公共 ボイドwhateverMethod(){ } }