- シングルトンは、クラスのインスタンスを1つだけ確実に
- シングルトンクラスは、独自のインスタンスを作成する必要があります
- シングルトンクラスは、静的な取得モードを提供します(通常のgetInstance()メソッド名)
最初の中国風の空腹
public class Singleton {
private static final Singleton instance = new Singleton();
public Singleton() {
//Empty
}
public static Singleton getInstance() {
return instance;
}
}
上記のコードでは、クラスの唯一のインスタンスを取得することができますが、時にJVMをロードするプロセスは、このインスタンスを初期化しますが、このインスタンスに使用されていない場合、それはメモリの無駄が発生します。この方法を使用することができますが、推奨されません
二怠惰なスタイル
public class LazySingleUnSafe {
private static LazySingleUnSafe instance;
private LazySingleUnSafe() {
}
public static LazySingleUnSafe getInstance() {
//一个线程进入了if (null == instance)判断语句块,还未来得及往下执行,
// 另一个线程也通过了这个判断语句
if (null == instance) {
return new LazySingleUnSafe();
}
return LazySingleUnSafe.instance;
}
}
上述した第1の方法は、複数のスレッド場合、最初のスレッドは、それが決定されると、式を飢えの問題を解決するが、唯一のシングルスレッドモードで使用することができ
if (null == instance)
この文は、それが複数のインスタンスを作成します、第二のスレッドがトゥーレと判断することができる、真であるので、複数のスレッドを使用することはできません
ロックされた第三怠惰な男
public class LazySingleSafe {
private static LazySingleSafe instance;
private LazySingleSafe() {
}
// 在这里加锁 但是影响性能
public synchronized static LazySingleSafe getInstance() {
if (null == instance) {
return new LazySingleSafe();
}
return LazySingleSafe.instance;
}
}
この方法は、あなたが第二のモードで問題を解決することができますが、それぞれの状態がロックを決定しますので、パフォーマンスの低下
第四モードDoubleCheck
public class LazySingleDoubleCheck {
private static LazySingleDoubleCheck instance;
private LazySingleDoubleCheck() {
}
//只有在两个线程同时抢锁的时候
public static LazySingleDoubleCheck getInstance() {
if (null == instance) {
synchronized (LazySingleDoubleCheck.class) {
if (null == instance) {
return new LazySingleDoubleCheck();
}
}
}
return LazySingleDoubleCheck.instance;
}
}
貧弱なパフォーマンスの問題を添加する方法で第三のロックモードに、この溶液は、インスタンスを直接決定決定されるロック状態の代わりに作成されたオブジェクトが返されたときに存在する。2つのスレッドがある場合でも、インスタンスは、決定されたヌルでありますしかし、プロセスの新しいインスタンスが、ロックは、このインスタンスの内部プロパティは、オブジェクトがまだインスタンス化されるとき、長い時間のための必要性の多くの例であれば、一つだけのスレッドがオブジェクトのインスタンスを作成しますが、それは実際の開発である場合になりますgetInstance()メソッドによって、この例を取るための第2のスレッドが存在する場合の時間は、ヌル値を取ります。
第DoubleCheck +揮発的
public class LazySingleDoubleCheckNotNull {
//在这里加 volatile 保证有序 保证可见性 在读的时候必须保证他已经写完
private static volatile LazySingleDoubleCheckNotNull instance;
private LazySingleDoubleCheckNotNull() {
}
public static LazySingleDoubleCheckNotNull getInstance() {
if (null == instance) {
synchronized (LazySingleDoubleCheckNotNull.class) {
if (null == instance) {
instance = new LazySingleDoubleCheckNotNull();
}
}
}
return LazySingleDoubleCheckNotNull.instance;
}
}
これは、第四のだけの方法よりもあり、追加の揮発性キーワード。
揮発性キーワードは、インスタンスが完全に終了したときに読み出すための第2のスレッド(このフォローアップには、キーワードの説明に焦点を当てる)ことを確実にします
静的な内部クラスを作成するための第六の方法
public class SingleInnerClass {
private SingleInnerClass() {
}
//外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE 调用的时候只创建一个 所以单例
private static class InstanceHolder {
private final static SingleInnerClass instance = new SingleInnerClass();
}
public static SingleInnerClass getInstance() {
return InstanceHolder.instance;
}
}
JVMはすぐにロードされない外部クラスと内部クラスをロードするときに、しかし、ロードするために行くために呼ばれたとき、それは前のレイジー・モード、およびセキュリティスレッドを確保するためのJVMローディング機構と同様であるので、このアプローチが推奨されます。
道の第七列挙
public class SingleEnum {
private SingleEnum() {
}
private enum Singleton {
INSTANCE;
private final SingleEnum instance;
Singleton() {
instance = new SingleEnum();
}
public SingleEnum getInstance() {
return instance;
}
}
public static SingleEnum getInstance() {
return Singleton.INSTANCE.getInstance();
}
}
私たちは、列挙を定義し、最初の時間は、本当に、それは、ロードされ、仮想マシンを初期化されます使用し、この初期化プロセスは、スレッドセーフである(クラスローダにフォローアップの指示に焦点を当てます)
ます。https://www.jianshu.com/p/9698b0cece09で再現