シングルトンモデル:クラスのインスタンスを1つだけ必要とし、グローバルアクセスメソッドを提供します。
1.遅延および空腹のシングルトンモデル
1.1怠け者
遅延シングルトンパターンは、クラスが読み込まれるときに静的な初期化によってインスタンス化されます。
public class Layzerbones {
private static Layzerbones layzer = new Layzerbones();
private Layzerbones(){}
public static Layzerbones getInstance(){
return layzer;
}
}
1.2空腹
ハングリーシングルトンモードは、最初に呼び出されたときにインスタンス化されます。
パブリッククラスBadmash {
プライベート静的Badmash badmash;
プライベートBadmash(){}
パブリックスタティック同期Badmash getInstance(){//メソッド一
if(badmash == null){
badmash = new Badmash();
}
badmashを返す。
}
public static Badmash getInstance2(){//メソッド二
if(badmash == null){
synchronized(Badmash.class){
if(badmash == null){
badmash = new Badmash();
}
}
}
badmashを返す。
}
}
上記の2つのシングルトンモデルに共通するもの:
1.現在のクラスが静的メンバー変数として使用されている; 2.コンストラクターがプライベート化されている; 3.静的でアクセス可能なインスタンス化メソッドが提供されている;
違いは次のとおりです。
1.レイジースタイル:スレッドセーフ。
2.空腹のハンスタイル、スレッドは安全ではないため、ロックを増やす必要があります。
3.空腹の中国スタイルのロックには2つの方法があります。1つはメソッドにロックを追加する方法、もう1つはクラスのバイトコードファイル、もう1つは同期コードブロックで、ロックはカスタマイズ可能です。
4.同期化コードブロックの二重検証の目的は、実行の効率を向上させることです。
2.空腹の中国のダブルチェックロックの問題と最適化
問題は、コンパイラによるコンパイル中に既存のロジックコードが並べ替えられる可能性があることです。
これは「JAVA Concurrent Programming Art」の図であり、以下に示すように、問題を明確に示しています。
通常のオブジェクトの初期化の順序は次のとおりです。1。最初にオブジェクトにメモリ空間を割り当てます; 2.オブジェクトを初期化します; 3.初期化されたインスタンスを割り当てられたメモリアドレスにポイントします
しかし、問題は、JMMの内部の並べ替え、オブジェクトの初期化、およびインスタンスアドレスがメモリアドレスを指すため、並べ替えることができることです。
次に、問題が発生します。オブジェクトが初期化される前は、オブジェクトはすでにメモリアドレスを指しており、オブジェクトはnullです。別のスレッドが再びアクセスすると、再び判断してnullになり、オブジェクトを再度初期化します。
もちろん、この種の問題については、解決することをお勧めします。volatile修飾子を静的メンバーに追加します。これは、変更された変数をアトミックにする軽量ロックです。
プライベート揮発性静的Badmash badmash;
もちろん、この問題を回避する方法は他にもあります。
3.静的内部シングルトン設計モデル
上記のオブジェクトの初期化と再配置の問題を回避するには、初期化プロセスでクラスロックの原則を使用して、内部クラスを通じてシングルトンを実装します。
public class Singleton {
private Singleton(){
}
public static Singleton getInstance(){
return Inner.instance;
}
プライベート静的クラスInner {
プライベート静的最終シングルトンインスタンス= new Singleton();
}
}
4.シングルトンパターンを列挙する
1.列挙にインスタンス列挙INSTINCTを設定します。
2.次に、プライベートコンストラクターで初期化する必要があるオブジェクトを初期化します。
3. インスタンスを取得するための外部非静的メソッドを提供する
public enum SingleEnum {
INSTINCT;
プライベートユーザーuser;
SingleEnum(){
user = new User();
}
public User getInstance(){
return user;
}
}
上記は最も一般的なシングルトンモデルです。
これで終了です!