详说单例模式

懒汉式:

public class Singleton {
    private static Singleton instance;
    private Singleton (){}  //不让外部new
    public static synchronized Singleton getInstance (){  //去掉synchronized是线程不安全的
        if (instance == null) { //1:A线程执行
            instance = new Singleton(); //2:B线程执行
        }
        return instance;
    }
}

“这个人比较懒,等着你用的时候才去实例化”,延迟加载。
优点:第一次调用才初始化,避免内存浪费
缺点:每次获取实例都要加锁,耗费资源,其实只要实例已生成,以后就不需要再锁了

饿汉式:

public class Singleton {
    private static Singleton instance = new Singleton(); //声明静态私有类变量,且立即实例化, 
                                                         //保证实例化一次
    private Singleton(){} //构造方法,防止外部实例化,通过反射是可以实例化的,不考虑此种情况
    public static Singleton getInstance() {
        return instance;
    }
}

“因为饿所以要立刻吃饭,刻不容缓”,在定义类的静态私有变量同时进行实例化
优点:线程安全,没有加锁,执行效率会更高
缺点:类加载时就初始化,浪费内存。

双重检查加锁模式:

public class Singleton {
    private volatile static Singleton singleton;  // 注意:加了volatile关键字
    private Singleton(){}
    public static Singleton getInstance(){
        if(singleton == null){ //第一次检查
            synchronized(Singleton.class){ //加锁
                if(singleton == null){ //第二次检查
                    singleton = new Singleton(); //
                }
            }
        }
        return singleton;
    }
}

这种模式可能会引起空指针异常,new 一个对象需要经历:分配内存空间-初始化-引用赋值(指向对象的地址)过程,而且java中存在cpu指令重排序,因此在多线程环境下线程一执行 可能执行new对象:分配内存空间-引用赋值-初始化,当执行到引用赋值时,线程二会看到instance!=null,但这时,对象并未完成初始化,对象是空的,直接使用会空指针异常。因此这种方式也是线程不安全的。

volatile 在这的作用就是禁止指令重排序,从而使对象的创建严格按照分配内存空间-初始化-引用赋值(指向对象的地址)过程,实现了线程安全。

静态内部类:

public class Singleton {
    private Singleton(){}
    public static Singleton getInstance(){
        return InnerClassSingleton.singleton;
    }
    private static class InnerClassSingleton{
        protected static final Singleton singleton = new Singleton();
    }
}

优点:既避免了同步带来的性能损耗,又能够延迟加载

枚举:

public enum Singleton {
    INSTANCE;
    public void init(){
        System.out.println("资源初始化。。");
    }
}

天然线程安全,可防止反射生成实例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值