私はLazyReference
クラスを数年間使用しています(もちろん定期的にではありませんが、非常に役立つ場合もあります)。クラスはここで見ることができます。クレジットは、Robbie Vanbrabant (クラス作成者) と Joshua Bloch の著名な「Effective Java 2nd edt」に贈られます。(元のコード)。
クラスは (Java 5+ で) 正しく動作しますが、潜在的な問題が 1 つあります。instanceProvider
返された場合(Guiceの契約null
に従ってはいけませんが…)、メソッドを実行するたびに LOCK が保持され、何度も呼び出されます。契約を破った人には良い罰のように見えますが (he-he)、値を設定する可能性のあるフィールドを遅延して初期化する必要がある場合はどうすればよいでしょうか?Provider.get()
LazyReference.get()
instanceProvider.get
null
LazyReference を少し変更しました。
public class LazyReference<T> {
private final Object LOCK = new Object();
private volatile T instance;
private volatile boolean isNull;
private final Provider<T> instanceProvider;
private LazyReference(Provider<T> instanceProvider) {
this.instanceProvider = instanceProvider;
}
public T get() {
T result = instance;
if (result == null && !isNull) {
synchronized (LOCK) {
result = instance;
if (result == null && !isNull) {
instance = result = instanceProvider.get();
isNull = (result == null);
}
}
}
return result;
}
}
私見は問題なく動作するはずです(別の意見がある場合は、コメントや批判を投稿してください)。しかし、ブール値volatile
から修飾子を削除するとどうなるでしょうか(もちろんそのままにしておきます)。それでも正しく動作しますか?isNull
instance