要件:
1.スレッドセーフ
2.オブジェクトの直列化可能性-シングルトンの変更
3. try-catchブロックでオブジェクトを作成する制御性
4.コンストラクターからシングルトンオブジェクトを作成する
5.パフォーマンスを向上させるための、シングルトンオブジェクト参照のシリアル化不可能な取得。
6.オブジェクトの「遅延」初期化-シングルトン
オプション1
public class Singleton { private static volatile Singleton instance; static { System.out.print("Singleton class Initializator\r\n"); try { InitSingleton(); } catch (Exception e) { System.out.print("Exception occurred\r\n"); } } private static synchronized void InitSingleton() { if (instance == null) instance = new Singleton(); } public Singleton() { System.out.print("Singleton has been initialized\r\n"); } public static Singleton getInstance() { return instance; } }
提案された実施形態では、オブジェクトへの参照を作成する同期メソッドの呼び出しは、オブジェクトのメンバー変数の初期化と同じレベルで実際に実行される、オブジェクトのいわゆる静的初期化子から行われ、コンストラクタが呼び出される前に実行され、「設計により直列化可能でなければならない」 「。 しかし、イニシャライザの自己シリアル化への期待は大きくないため、 揮発性修飾子を使用してシングルトンオブジェクトへの静的参照を提供しました。これにより、異なるスレッドでの静的変数の値の一貫性が保証され、シングルトンオブジェクトを作成する静的メソッドは同期修飾子を提供しました。 1つのスレッドで。
2番目のオプションは、初期化と同じ初期化の原則を使用するという点で最初のオプションと似ていますが、パフォーマンスのためにシングルトンオブジェクトへの静的参照用のvolatile修飾子がないことで区別され、オブジェクト作成の同期は、以前に実行されたクラスのメンバーオブジェクトのブロックに基づいています。 同時に、記事「Javaでのシングルトンの修正」のコメントで提案されたアイデアが使用されました 。
オプション2
public class Singleton { private static Singleton instance; private static final Object lock = new Object(); private static boolean isInitialized = false; static { System.out.print("Singleton class Initializator\r\n"); try { synchronized (lock) { if (!isInitialized) if (instance == null) { instance = new Singleton(); isInitialized = true; } } } catch (Exception e) { System.out.print("Exception occurred\r\n"); } } public Singleton() { System.out.print("Singleton has been initialized\r\n"); } public static Singleton getInstance() { return instance; } }