单例模式在设计模式中也是比较常见的一种模式。
对于怎么实现单例,网上也比较多的解释,这里我就不说其中的饱汉、饿汉模式了。
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();的时候,会有大量对象创建,很可能导致内存溢出。