手書きシングルトンパターン
面接の際、シングルトンモードについてお聞きしましたが、シングルトンモードは最もシンプルなモードですが、上手く使いたいと言うと大変です。
空腹モード
public staticSingleton { private static Singleton = new Singleton(); private Singleton(){} public static getSingleton(){ return sinleton; }
これは目的は簡単ですが、オブジェクトを遅延して作成することは不可能ですが、オブジェクトをできるだけ遅くロードして負荷を軽減することがよくあるため、レイジーモードは次のようになります。
public class Singleton { private static Singleton singleton = null; private Singleton(){} public static Singleton getSingleton(){ if(singleton == null){ singleton = new Singleton(); } シングルトンを返す。 } }
スレッドセーフな書き込みを検討してください。
public class Singleton { private static volatile Singleton singleton = null; private Singleton(){} public static Singleton getSingleton(){ synchronized(Singleton.class){ if(singleton == null){ singleton = new Singleton(); } } シングルトン返します。 } }
スレッドと効率の両方を念頭に置いて書く
public class Singleton { private static volatile Singleton singleton = null; private Singleton(){} public static Singleton getSingleton(){ if(singleton == null){ synchronized(Singleton.class){ if(singleton == null){ singleton = new Singleton(); } } } シングルトン返します。 } }
2つのnullは不要です。実際には、同時実行性が向上します。シングルトンモードでは、newの状況は非常にまれです。並列読み取り操作の大部分、つまりもう1つのnullは、ほとんどのロック操作を削減し、実行効率が向上します目的は達成されました。
その他の穴
volatitleの最初のレベルはよく知られています。つまり、変数のワーキングメモリの変更はメインメモリにすぐに書き込まれます。メモリ内で作業する場合はスレッドを排他的にします。メインメモリスレッドは共有されます。volatitleの2番目のレイヤーは、オーダーからのオーダーの最適化を禁止することを意味します。スレッドの安全性は、jdk1.5より前では保証できません。
静的内部クラスパターン
では、読み込みを遅らせてスレッドの安全性を確保する簡単な方法はありますか?シングルトンインスタンスを静的内部クラスに入れることができます。これにより、シングルトンクラスが読み込まれるときに静的インスタンスがオブジェクトを作成することを回避できます。静的内部クラスは1回だけ読み込まれるため、この書き込みメソッドもスレッドセーフです
public class Singleton { private static class Holder { private static Singleton singleton = new Singleton(); } private Singleton(){} public static Singleton getSingleton(){ return Holder.singleton; } }
列挙
public enum Singleton { INSTANCE; プライベート文字列名。 public String getName(){ return name; } public void setName(String name){ this.name = name; } }
スレッドセーフであり、リフレクションがコンストラクターを強制的に呼び出すのを防ぐことに加えて、列挙型を使用すると、逆シリアル化中に新しいオブジェクトが作成されないようにする自動シリアル化メカニズムも提供されます。したがって、Effective Javaでは、シングルトンを実装するために可能な限り列挙を使用することをお勧めします。
まとめ
最後に、どのような計画をとっても、シングルトンの3つの主要な点に留意してください。
- スレッドセーフ
- 遅延読み込み
- シリアライゼーションとデシリアライゼーションのセキュリティ