例では、略単一モード、モードと飢えレイジーモードの2種類に分けました。
まず、空腹の男性モード
オブジェクトを作成するには、システム上で実行して、問題についてはあまり考えていない、それは何回も作成することができ、複数のオブジェクトがあります。しかし、明らかにメモリの無駄があるでしょう。スレッドセーフ
public class Singleton{
//类加载时就初始化
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
第二に、怠惰なモード
唯一のインスタンスを作成するために取得しているが、ときにスレッドセーフでは。
public class Singleton2 {
private static Singleton2 singleton;
private Singleton2(){
}
public static synchronized Singleton2 getInstance(){
if(singleton == null)
singleton = new Singleton2();
return singleton;
}
}
第三に、怠惰なダブルパターンロックモード
public class Singleton3 {
private volatile static Singleton3 singleton;//1
private Singleton3(){
}
public static Singleton3 getInstance(){
if(singleton == null){ //2
synchronized(Singleton3.class){ //3
if(singleton == null){ //4
singleton = new Singleton3();
}
}
}
return singleton;
}
}
それは2ヶ所、1234に分けることができます
1、ステップ1
基本的に;)シングルトン=新しいSingleton3(そのため非アトミック操作、実際には、JVMでおそらく3つのことを行います。
1.シングルトンにメモリを割り当てます
2.コールSingleton3工事完了の初期化
割り当てられたメモリ空間にシングルトンオブジェクトの参照ポインタを作るために3(これはシングルトンがNULLでない行われます)
しかしながら、本インスタントコンパイラのJVMに命令並べ換え最適化する。それは保証されないために、上記第二及び第三のステップである、とすることができる実行の最終的な順序であってもよい1 1-2-3 3-2。次に、後者は、次に3で終了、2は、2つのスレッドが押収され、前に行われず、次いで、シングルトンが非ヌルを有している(ただし、初期化されていない)場合、2つのスレッド・リターン直接シングルトンそして、エラー。
注:揮発性ブロッキング=この文章内の新しいシングルトン()[1-2-3]命令再配置シングルトンではなく、書き込みの動作を保証するためには、([1-2-3])は、前に行われていません()の呼び出しは、インスタンス== nullを(あれば)をお読みください。
図2に示すように、ステップ234
防止するために、複数回インスタンス化:内層を分析
スレッド3はまた、決定され、オブジェクトがインスタンス化されるスレッドは、内層1を完了したとき、状況を考えるしようgetInstace関数呼び出し、外ねじのない増加がないかどうかを決定する:外側の分析を図3は、またはスレッド2の完了を待ち続けるために、外層は、待機直接インスタンス化オブジェクトを返す必要がない、一緒に決定されます。
第四に、怠惰なモードメモリリーク
アンドロイドでは、活性は、時には、次の行に沿って存在するであろうように、シングルモードの実施例として使用されます
public class Singleton3 {
private volatile static Singleton3 singleton;//1
private Singleton3(){
this.mContext = mContext;
}
public static Singleton3 getInstance(){
if(singleton == null){ //2
synchronized(Singleton3.class){ //3
if(singleton == null){ //4
singleton = new Singleton3(context);
}
}
}
return singleton;
}
}
コンテキストは、通常の活動に渡された場合は、サービスや他のコンテキストでは、メモリリークにつながることができました。
私たちは活動を終了したときにそのため、活動なしの使用が、静的なシングルトン(アプリケーションのライフサイクル全体を通じて存在が)活動オブジェクトの解放につながる、この活動への参照を保持し続けるようシングルトンを回復することはできませんので、彼らメモリリークが生じます。
修正方法、グローバルコンテキストにコンテキストパラメータ:
private Singleton3(){
this.mContext =mContext.getApplicationContext();
}
参考:
https://blog.csdn.net/Imobama/article/details/81093394