JAVA架构师之路三:设计模式之单例模式

JAVA架构师之路二:设计模式之工厂模式

日头没有辜负我们,我们也切莫辜负日头。——沈从文

代码世界中也存在以下顺口溜:

我单身,我骄傲,我为国家省套套。
我单身,我自豪,我为祖国省橡胶。

单例模式虽然简单,但真正懂的内行的人并不多,今天挑战全网最全的经典设计模式之单例模式。

1. 单例模式

定义

确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
隐藏其构造方法
属于创建型设计模式

适用场景

确保任何情况下都绝对只有一个实例
ServletContext、ServletConfig、ApplicationContext、DBPool

2. 饿汉式单例

定义

系统初始化的时候就加载,不管有没有用到这个单例。

优点

执行效率高,性能高,没有任何的锁

缺点

某些情况下,可能会造成内存浪费
能够被反射破坏

代码

public class HungrySingleton {
   

    private static final HungrySingleton singleton = new HungrySingleton();

    private HungrySingleton(){
   }

    public static HungrySingleton getInstance() {
   
        return singleton;
    }
}

3. 懒汉式单例

定义

系统初始化的时候不创建实例,只有用到的时候才创建实例。

优点

节省了内存

缺点

synchronized造成性能低下
能够被反射破坏

3.1 方法加锁写法

代码

public class LazySingleton {
   

    private static LazySingleton singleton = null;

    private LazySingleton(){
   }


    /**
     * 版本1
     * @return
     */
    public static synchronized LazySingleton getInstance() {
   
        if (null == singleton) {
   
            singleton = new LazySingleton();
        }
        return singleton;
    }
}

3.2 代码块加锁写法

代码

public class LazySingleton {
   

    private static LazySingleton singleton = null;

    private LazySingleton(){
   }
    
    /**
     * 版本2 相比版本1优化一点点
     * @return
     */
    public static LazySingleton getInstance() {
   
        synchronized (LazySingleton.class) {
   
            if (null == singleton) {
   
                singleton = new LazySingleton();
            }
        }
        return singleton;
    } 
}

3.3 双重判断加锁写法

陷阱案例

public class LazySingleton {
   

    private static LazySingleton singleton = null;

    private LazySingleton(){
   }
    
    /**
     * 版本3 双重判断
     * @return
     */
    public static LazySingleton getInstance() {
   
        if (null == singleton) {
   
            synchronized (LazySingleton.class) {
   
                if (null == singleton) {
   
                    singleton = new LazySingleton();
                }
            }
        }
        return singleton;
    }
}

版本3看起来相比版本2优化了不少,但其实这种双重判断在生产环境有一个极大的漏洞陷阱,就是指令重排序,有需要了解的可以在评论区留言。解决方案也很简单,就是 volatile 关键字。它可以限制指令重排序。

正确写法

public class LazySingleton {
   

    private volatile static LazySingleton singleton = null;

    private LazySingleton(){
   }
    
    
  • 24
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 25
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值