如果需要使用双重校验锁实现单例,可以考虑使用Guava
的Suppliers.memoize()
,避免手写样板代码。
package current;
import java.util.Random;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
/**
* Created on 2022-09-29
*/
public class SingletonTest {
private static final Supplier<SingletonTest> heavySupplier =
Suppliers.memoize(SingletonTest::new);
private SingletonTest() {
System.out.println("being created" + new Random().nextInt(9));
}
public static SingletonTest getSingleton() {
return heavySupplier.get();
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
SingletonTest heavyObject = SingletonTest.getSingleton();
System.out.println(heavyObject);
}
}
}
结果
being created2
current.SingletonTest@3d24753a
current.SingletonTest@3d24753a
current.SingletonTest@3d24753a
current.SingletonTest@3d24753a
current.SingletonTest@3d24753a
Process finished with exit code 0
Suppliers.memoize方法
/**
* Returns a supplier which caches the instance retrieved during the first
* call to {@code get()} and returns that value on subsequent calls to
* {@code get()}. See:
* <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>The returned supplier is thread-safe. The supplier's serialized form
* does not contain the cached value, which will be recalculated when {@code
* get()} is called on the reserialized instance.
*
* <p>If {@code delegate} is an instance created by an earlier call to {@code
* memoize}, it is returned directly.
*/
public static <T> Supplier<T> memoize(Supplier<T> delegate) {
return (delegate instanceof MemoizingSupplier)
? delegate
: new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
}
@VisibleForTesting
static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
transient volatile boolean initialized;
// "value" does not need to be volatile; visibility piggy-backs
// on volatile read of "initialized".
transient T value;
MemoizingSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
@Override public T get() {
// A 2-field variant of Double Checked Locking.
if (!initialized) {
synchronized (this) {
if (!initialized) {
T t = delegate.get();
value = t;
initialized = true;
return t;
}
}
}
return value;
}
@Override public String toString() {
return "Suppliers.memoize(" + delegate + ")";
}
private static final long serialVersionUID = 0;
}