1. お腹を空かせた中華風シングルトン
次のようにコードをコピーします。
パブリック クラス シングルトン {
プライベート最終静的シングルトン INSTANCE = new Singleton();
プライベートシングルトン() { }
public static Singleton getInstance() {
インスタンスを返します。
}
}
2. 内部クラスの助けを借りて
Java メカニズムでは、内部クラス SingletonHolder は getInstance() メソッドが初めて呼び出されたときにのみロードされる (遅延実装される) と規定されており、そのロード プロセスはスレッドセーフであるため、これは遅延シングルトンです。インスタンスは、内部クラスがロードされるときに一度インスタンス化されます。
次のようにコードをコピーします。
パブリック クラス シングルトン {
プライベートシングルトン() { }
プライベート静的クラス SingletonHolder {
プライベート最終静的シングルトン INSTANCE = new Singleton();
}
public static Singleton getInstance() {
SingletonHolder.INSTANCE を返します。
}
}
3. 通常のロックソリューション
次のようにコードをコピーします。
パブリック クラス シングルトン {
プライベート静的シングルトン インスタンス = null;
プライベートシングルトン() { }
public static synchronized Singleton getInstance() {
if(インスタンス == null) {
インスタンス = 新しいシングルトン();
}
インスタンスを返します。
}
}
スレッドの安全性の問題は解決されましたが、getInstance を呼び出すすべてのスレッドはロックする必要があります。getInstance が最初に呼び出されたときのみロックする必要があります。以下の二重検出の解決策を参照してください。
4. 二重検出ですが書き込み方法に注意してください
次のようにコードをコピーします。
パブリック クラス シングルトン {
プライベート静的シングルトン インスタンス = null;
プライベートシングルトン() { }
public static Singleton getInstance() {
if(インスタンス == null) {
同期(Singleton.class) {
シングルトンの温度 = インスタンス;
if(temp == null) {
temp = 新しいシングルトン();
インスタンス=一時
}
}
}
インスタンスを返します。
}
}
命令の並べ替えの問題により、次のように直接記述することはできません。
パブリック クラス シングルトン {
プライベート静的シングルトン インスタンス = null;
プライベートシングルトン() { }
public static Singleton getInstance() {
if(インスタンス == null) {
同期(Singleton.class) {
if(インスタンス == null) {
インスタンス = 新しいシングルトン();
}
}
}
インスタンスを返します。
}
}
ただし、インスタンス変数が volatile で変更されている場合は、instance = new Singleton(); の対応する命令もスレッド化されません。安全:
パブリック クラス シングルトン {
プライベート静的揮発性シングルトン インスタンス = null;
プライベートシングルトン() { }
public static Singleton getInstance() {
if(インスタンス == null) {
同期(Singleton.class) {
if(インスタンス == null) {
インスタンス = 新しいシングルトン();
}
}
}
インスタンスを返します。
}
}