java单例空指针总结_java单例模式总结

常见安全的单例实现代码和自己的一点理解。

一、 饿汉模式(静态初始化)

class Singleton{

private Singleton(){

}

private static Singleton cache=new Singleton();

public static Singleton getInstance(){

return Internal.cache;

}

}

实现最为简单,但是如果Singleton的任何一个静态字段(非常量,常量是被动引用,在编译时通过常量传播优化,放入常量池,转化为了对常量池的引用)或者静态方法被调用则会初始化。线程安全有虚拟机的保证,对象的实例化是在类加载的初始化阶段。初始化的时机详见:深入理解java虚拟机p210

二、双重检查锁(dcl)

class Singleton{

private Singleton(){

}

private volatile static Singleton cache;

public static Singleton getInstance(){

if(cache==null){

synchronized (Singleton.class){

if(cache==null){

cache=new Singleton();

}

}

}

return cache;

}

}

双重检查锁是为了解决资源初始化较慢或者资源较重的场景下延迟初始化,利用synchronized关键字保证线程安全。饿汉模式是利用虚拟机本身保证类加载的的线程安全性。但是dcl本身每次都需要检查该对象是否实例化,所以引出下面的模式

三、 延迟占位类

class Singleton{

private Singleton(){

}

private static final class Internal{

static Singleton cache=new Singleton();

}

public static Singleton getInstance(){

return Internal.cache;

}

}

延迟占位类结合前两种的优势,消除了同步并且实现了延迟初始化。延迟占位类模式的线程安全也是由虚拟机来保证的,这里需要理解的是为什么能延迟初始化。相比于饿汉模式,延迟占位类模式可以实现调用getInstance方法才去初始化该类

四、枚举实现

effective java中的推荐做法。我找了一个jdk中的实现如下:

enum NaturalOrderComparator implements Comparator> {

INSTANCE;

@Override

public int compare(Comparable c1, Comparable c2) {

return c1.compareTo(c2);

}

@Override

public Comparator> reversed() {

return Comparator.reverseOrder();

}

}

枚举本身更加安全,虚拟机层面阻止了通过反射去实例化一个类导致单例破坏的场景。

最后

此外还有懒汉模式(线程不安全)和懒汉模式直接加synchronized(性能问题)的,这种代码比较简单,实际也没使用的意义就不展开了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值