我正在尝试为下面的类实现Singleton
模式。我应该在JVM中随时只有一个类SingletonClass
的实例。
以下代码是否满足Singleton模式?请提供您的建议。
public class SingletonClass {
private static SingletonClass cache = null;
private static final Object LOCK = new Object();
// creates one single instance of the class
public static SingletonClass getInstance() {
if (cache == null) {
synchronized (LOCK) {
if (cache == null) {
cache = new SingletonClass();
}
}
}
return cache;
}
public static void main(String[] args) {
SingletonClass.getInstance();
}
}
答案 0 :(得分:2)
有一篇很好的文章介绍了实现单例模式的不同方法,包括你的方式: Reg's Tech article about Singleton
正如文章中提到的那样(如果你希望模式是100%线程安全的),也将SingletonClass字段声明为volatile。此外,您不需要将Object作为锁。只需使用synchronized(SingletonClass.class)
答案 1 :(得分:1)
这是实现单例的非阻塞尝试。
public final class SingletonRef<T> {
private static final Lock lock = new ReentrantLock(); // Atomic boolean may be??
private static final TimeUnit timeUnit = TimeUnit.SECONDS;
private final AtomicReference<T> instance;
private final Supplier<T> refSupplier;
private final long timeout;
public SingletonRef(final Supplier<T> refSupplier, long timeout) {
this.refSupplier = refSupplier;
this.timeout = timeout;
this.instance = new AtomicReference<>();
}
public T get() {
if (instance.get() == null) {
// multiple threads could arrive here here concurrently
try {
// keep looping until the thread is able to acquire the lock
while (!lock.tryLock()) ;
// only one thread at a time will arrive here because other threads will be busy waiting in the loop above.
if (instance == null) {
ExecutorService executor = Executors.newFixedThreadPool(1);
// if the instance is still null then it either means that
// - this is the first attempt to create this object
// - or the previous attempt to create the instance failed. Let's try again!!
CompletableFuture<T> fut = CompletableFuture.supplyAsync(refSupplier, executor);
instance.set(fut.get(timeout, timeUnit));
executor.shutdown();
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
// handle exception however you like. I am gonna rethrow as Runtime exception for now.
throw new RuntimeException(e);
} finally {
// release the lock
lock.unlock();
}
}
return instance.get();
}
}
使用示例
/**
* Very Expensive Service!! Cannot afford to create multiple objects
*/
public final class SatelliteService {
private static final SingletonRef<SatelliteService> ref = new SingletonRef<>(SatelliteService::new, 5);
static SatelliteService get() {
return ref.get();
}
private SatelliteService() {
}
}
P.S:这是未经测试的代码。如果您发现任何问题,请测试并告诉我。谢谢!