单例模式与对象锁定

时间:2016-03-14 11:24:41

标签: java singleton

我正在尝试为下面的类实现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();
    }
}

2 个答案:

答案 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:这是未经测试的代码。如果您发现任何问题,请测试并告诉我。谢谢!