*饿汉式*单例和*懒汉式*单例的比较, 以及推荐的单例模式写法

饿汉式实现方式

class EagerSingleton { 
    private static final EagerSingleton instance = new EagerSingleton(); 
    private EagerSingleton() { } 
 
    public static EagerSingleton getInstance() {
        return instance; 
    }   
}

懒汉式实现方式(线程安全版本)

class LazySingleton { 
    private volatile static LazySingleton instance = null; 
 
    private LazySingleton() { } 
 
    public static LazySingleton getInstance() { 
        //第一重判断
        if (instance == null) {
            //锁定代码块
            synchronized (LazySingleton.class) {
                //第二重判断
                if (instance == null) {
                    //创建单例实例
                    instance = new LazySingleton(); 
                }
            }
        }
        return instance; 
    }
}

PS:为什么要双重检查呢?
假如在某一瞬间线程A和线程B都在调用getInstance()方法,此时instance对象为null值,均能通过instance == null的判断。由于实现了synchronized加锁机制,线程A进入synchronized锁定的代码中执行实例创建代码,线程B处于排队等待状态,必须等待线程A执行完毕后才可以进入synchronized锁定代码。但当A执行完毕时,线程B并不知道实例已经创建,将继续创建新的实例,导致产生多个单例对象,违背单例模式的设计思想.

比较

饿汉式懒汉式
占用内存情况类被加载就占用着内存被需要用的时候才初始化
线程安全类被加载的时候就已经实例化, 不用考虑多线程访问问题需要双重检查锁来保证线程安全
性能首次访问的时候涉及实例化, 实例化可能耗费大量时间,性能自然会降低

一个更好的单例实现方法

饿汉式耗内存, 懒汉式耗性能,这里有个方式结合2者优点: 称为Initialization on Demand Holder(IoDH)技术
翻译成中文好像叫按需初始化…
说人话就是使用静态内部类

public class Singleton {

    public static Singleton getInstance(){
        return Inner.instance;
    }

    private Singleton(){

    }

    //内部类,默认不加载
    static class Inner {
        private final static Singleton instance = new Singleton();
    }

    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2);
    }
}

运行上述代码, 运行结果是true, 即创建的2个对象是同一个对象. 由于静态单例对象没有作为Singleton的成员变量直接初始化, 因此类加载的时候不会实例化Singleton(长期占据内存), 第一天调用getInstance()时将加载内部类Inner, 在该内部类中定义了一个static类型的变量instacne, 此时会首先初始化一这个成员变量,由于Java虚拟机来保证其线程安全性, 确保该成员变量只能初始化一次. 由于getInstance()方法没有任何线程锁定, 因此性能不会造成任何影响.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值