设计模式之单例模式

一 单例模式

1.1 单例模式

单例模式:保证一个类在全局只有一个实例,并对外提供一个访问接口。

1.2 使用场景

1 需要统计全局数据

2 创建一个对象需要耗费资源过多,比如IO或者数据库资源

3 一般工具类都会单例模式

二 优点和缺点

优点:

内存只有一个或者极少实例,减少了频繁创建对象的开销,节省内存等资源,有利于提升性能

缺点:

单例模式扩展比较困难,一般都需要修改代码

三 代码实例

单例模式的七种实现方式:

3.1饥汉式

public class SingletonA {
    private static SingletonA singletonA = new SingletonA();
    private SingletonA(){ }
    public static SingletonA getInstance(){
        return singletonA;
    }
}

3.2 懒汉式,非线程安全

public class SingletonB {

    private static SingletonB singletonB = null;

    private SingletonB(){ }

    public static SingletonB getInstance(){

        return singletonB == null ? new SingletonB() : singletonB;

    }

}

3.3 懒汉式,线程安全

public class SingletonC {

    private static SingletonC singletonC = null;

    private SingletonC(){ }

    public static SingletonC getInstance(){

        synchronized (SingletonC.class) {

            return singletonC == null ? new SingletonC() : singletonC;

        }

    }

}

3.4 懒汉式,双重检验锁

public class SingletonD {

    private static SingletonD singletonD = null;

    private SingletonD(){ }

    public static SingletonD getInstance(){

        if (singletonD == null) {

            synchronized (SingletonD.class) {

                return singletonD == null ? new SingletonD() : singletonD;

            }

        }

        return singletonD;

    }

}

3.5 静态内部类实现

通过JVM类加载机制来保证初始化实例的时候只存在一个线程,避免线程安全问题,饿汉式的Singleton类被加载时,就会实例化,而静态内部类这种,当Singleton类被加载时,不会立即实例化,调用getInstance() 方法才会装载SingletonHolder类,从而完成Singleton的实例化。

public class SingletonE {

    private SingletonE(){ }

    public static final SingletonE getInstance(){

        return SingletonHolder.INSTANCE;

    }



    private static class SingletonHolder {

        private static final SingletonE INSTANCE = new SingletonE();

    }

}

3.6 基于volatile实现的单例(最终解决方案)

new的时候首先分配内存,然后在分配的内存上创建单例实例,最后将引用指向这个实例。但是可能存在指令重排序的问题,有可能首先分配内存,再将引用指向这个实例,最后分配的内存上创建单例实例

因为new这个过程并不是原子性的,所以可能导致将引用指向这个实例线程切换了,导致返回的对象是null

解决办法: 避免指令重排序

final? 只能避免指令重排序,不能保证可见性

volatile: 既可以保证可见性,又能避免指令重排序

public class Singleton4 {

    private static volatile Singleton4 instance = null;

    private Singleton4() {

    }

    public static Singleton4 getInstance() {
        if (instance == null) {
            synchronized (Singleton4.class) {
                return instance == null ? new Singleton4() : instance;
            }
        }
        return instance;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫言静好、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值