单例模式不常见的设计

单例模式在设计模式中也是比较常见的一种模式。

对于怎么实现单例,网上也比较多的解释,这里我就不说其中的饱汉、饿汉模式了。

1.使用静态内部类

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton (){}
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

这种方法采用了懒加载的方式,Singleton类被加载了,但是并没有立即初始化,而是需要Singleton.getInstance()该方法来进行初始化。

2.使用枚举

public enum Singleton {
    INSTANCE;
    public void whateverMethod() {
    }
}

这种使用枚举的方法不仅可以实现线程安全,还能防止反序列化。

3.使用CAS

CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。实现单例的方式如下:

public class Singleton {
    private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();

    private Singleton() {}

    public static Singleton getInstance() {
        for (;;) {
            Singleton singleton = INSTANCE.get();
            if (null != singleton) {
                return singleton;
            }

            singleton = new Singleton();
            if (INSTANCE.compareAndSet(null, singleton)) {
                return singleton;
            }
        }
    }
}

使用CAS优点:不需要使用锁机制来保证线程安全,CAS是一种基于忙等待的算法,依赖底层硬件的实现,相对于锁它没有线程切换和阻塞的额外消耗,可以支持较大的并行度。

使用CAS缺点:如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销;

          如果多个线程同时执行到singleton = new Singleton();的时候,会有大量对象创建,很可能导致内存溢出。

猜你喜欢

转载自www.cnblogs.com/zhupblogs/p/12467178.html