Singleton パターンの問題点を解決するAdvertisement問題
要求されたオブジェクトを返すメソッド getInstance() 内でインスタンスを生成する場合のコードを書いてみる。
import java.util.*;
final class Single{
private static Vector list = null;
private Single(){} // インスタンス化禁止
// オブジェクトを利用するときはこのメソッドを使用。
public static Vector getInstance(){
// 生成されていなければ生成する。
if(list == null){
list = new Vector();
}
return list;
}
}
上記のコードの場合、getInstance() が複数のクライアントから同時に呼び出され、最初の処理が ifブロックに入り、new Vector() が実行される前に、後続の処理がifブロックに入った場合、new Vector() が2回実行されることになり、Singleton オブジェクトが複数生成されることになる。これを避けるために同期化を使用してプログラムを修正する。
import java.util.*;
final class Single{
private static Vector list = null;
private Single(){} // インスタンス化禁止
// オブジェクトを利用するときはこのメソッドを使用。
synchronized public static Vector gerInstance(){
// 生成されていなければ生成する。
if(list == null){
list = new Vector();
}
return list;
}
}
これで getInstance() メソッドが複数のクライアントから同時に呼ばれても、排他状態で実行されるようになるため、オブジェクトが複数生成されることはなくなる。ただし Singleton という制約を満たすことはできたが、この getInstance() メソッドが頻繁に呼ばれるメソッドの場合、待ち状態が多発することになり、パフォーマンスに著しい影響を及ぼすことになる。 これを解決するのがダブルチェックという方法である。ダブルチェックを使用してコードを修正してみる。 (注意)ダブルチェックはJVMの実装によって、正しく動作しない場合があります。
import java.util.*;
final class Single{
private static Vector list = null;
private Single(){} // インスタンス化禁止
// オブジェクトを利用するときはこのメソッドを使用。
public static Vector gerInstance(){
// 生成されていなければ生成する。
if(list == null){
synchronized(list){
if(list == null){
list = new Vector();
}
}
}
return list;
}
}
これで2重にインスタンスが生成される問題が解決され、さらに一度インスタンスが生成されれば2度と synchronized ブロックには到達しないため、パフォーマンスに影響を及ぼすこともなくなる。
Advertisement |
ショートカット・634トップページ・このカテゴリのトップページに戻る ・634ラボ サイト検索Y!ログール |