単一スレッドとマルチスレッドでの単一モードの異なる書き方
8893 ワード
単例モードはよく使われるデザインモードの一つですが、今日は異なるシーンでどのように単例を実現するかについてお話しします.
単一のインスタンス・モードの概念は、クラスが1つのインスタンスしかないことを保証し、そのグローバル・アクセス・ポイントにアクセスすることです.主な役割は、Javaアプリケーションでクラスクラスクラスが1つしか存在しないことを保証することです.
単例パターンは一般的に怠け者式と餓漢式に分けられる.
単例のいくつかの書き方:
1.怠け者式(即時ロード方式)
この書き方は比較的簡単で,クラスロード時にインスタンス化が完了し,スレッド同期の問題を回避した.しかし、このインスタンスを最初から最後まで使用したことがない場合は、メモリの無駄になります.
2.餓漢式(遅延負荷方式)
マルチスレッドではこの方式は使用できません.スレッド1が
マルチスレッド操作時の単一モード:
3.メソッドにsynchronizedを付ける(欠点:リソースの消費が多すぎる)
4.緊急法によるインスタンスの複数回作成(欠点:メモリ消費)
5.ダブルチェックロック法(推奨使用)
注意:ここで静的変数におけるvolatileキーワードの役割は主に2つある:1).異なるスレッドがこの変数を操作する際の可視性を保証した;2).命令の並べ替えが禁止されているのもこの点であり,複数のスレッドが操作されている場合,どのステップにおいてもinstanceの値が変更されていれば,メモリから直接読み込まれ,複数のインスタンスが作成されることはない.
6.列挙(少ない)
JDK 1.5に追加された列挙によって、一例モードが実現される.マルチスレッド同期の問題を回避するだけでなく、逆シーケンス化による新しいオブジェクトの再作成も防止できます.
単一のインスタンス・モードの概念は、クラスが1つのインスタンスしかないことを保証し、そのグローバル・アクセス・ポイントにアクセスすることです.主な役割は、Javaアプリケーションでクラスクラスクラスが1つしか存在しないことを保証することです.
単例パターンは一般的に怠け者式と餓漢式に分けられる.
単例のいくつかの書き方:
1.怠け者式(即時ロード方式)
public class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
この書き方は比較的簡単で,クラスロード時にインスタンス化が完了し,スレッド同期の問題を回避した.しかし、このインスタンスを最初から最後まで使用したことがない場合は、メモリの無駄になります.
2.餓漢式(遅延負荷方式)
public class Singleton {
private static Singleton uniqeInstance = null;
public static Singleton getInstance(){
if (uniqeInstance == null) {
uniqeInstance = new Singleton();
}
return uniqeInstance;
}
}
マルチスレッドではこの方式は使用できません.スレッド1が
if (uniqeInstance == null)
を実行しても、まだ実行が開始されていない場合、スレッド2もこの判断文に合格すると、複数のインスタンスが生成されます.マルチスレッド操作時の単一モード:
3.メソッドにsynchronizedを付ける(欠点:リソースの消費が多すぎる)
public class Singleton {
public static Singleton instance = null;
public static synchronized Singleton getInstance() {
if (instance == null ) {
instance = new Singleton();
}
return instance ;
}
}
4.緊急法によるインスタンスの複数回作成(欠点:メモリ消費)
public class Singleton {
public static Singleton instance = new Singleton();
public static Singleton getInstance() {
if (instance == null ) {
instance = new Singleton();
}
return instance;
}
}
5.ダブルチェックロック法(推奨使用)
public class Singleton {
public volatile static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null ) {
synchronized (Singleton.class) {
if (instance == null ) {
instance = new Singleton();
}
}
}
return instance;
}
}
注意:ここで静的変数におけるvolatileキーワードの役割は主に2つある:1).異なるスレッドがこの変数を操作する際の可視性を保証した;2).命令の並べ替えが禁止されているのもこの点であり,複数のスレッドが操作されている場合,どのステップにおいてもinstanceの値が変更されていれば,メモリから直接読み込まれ,複数のインスタンスが作成されることはない.
6.列挙(少ない)
public enum SingletonEnum {
INSTANCE;
public void whateverMethod() {
}
}
JDK 1.5に追加された列挙によって、一例モードが実現される.マルチスレッド同期の問題を回避するだけでなく、逆シーケンス化による新しいオブジェクトの再作成も防止できます.