非官方解读单例模式

顾名思义,单例模式,也就是在程序中只存在一个实例.比如常举的例子java.lang.Runtime 它定义了静态变量,私有了无参构造器,提供公开的public方法获取实例.这样的好处是我们经常需要一个实例来进行事件的处理,那就没必要去创造多个实例出来,给GC压力.

单例的种类

饿汉式

也就是初始即加载

静态变量
class Singleton {
    // 定义实例对象
    private final static Singleton singleton = new Singleton();

    // 私有化构造方法
    private Singleton() {}

    // 提供公开静态方法-唯一的获取方式
    public static Singleton getInstance() {
        return singleton;
    }
}

类型: 饿汉式-静态变量
原理: 在编译时已经创建,通过类加载器保证线程安全,静态成员变量在类加载中的准备阶段就划分内存区域并置零值, 通过final关键字,在准备时会用代码值覆盖零值,进行直接赋值,不会等待初始化阶段.
缺点: 类加载时创建,这样如果程序启动有大量的创建,会导致内存浪费以及cpu使用达到峰值,有风险性操作,不能做到即用即加载.这是线程安全的.使用jvm类加载机制

静态代码块
class Singleton1 {
    // 定义实例对象
    private static Singleton1 singleton;

    static {
        singleton = new Singleton1();
    }

    // 私有化构造方法
    private Singleton1() {}

    // 提供公开静态方法-唯一的获取方式
    public static Singleton1 getInstance() {
        return singleton;
    }
}

类型: 饿汉式-静态代码块
原理: 也是通过类加载机制,静态代码块在类加载中的初始化时进行赋值,两者的差异是在类加载不同阶段.
缺点: 类加载时创建,这样如果程序启动有大量的创建,会导致内存浪费以及cpu使用达到峰值,有风险性操作,不能做到即用即加载

懒汉式

使用时再加载

懒加载(线程不安全)
class SingletonLazy1 {
	// 错误示范,线程不安全
    private static SingletonLazy1 singleton;

    private SingletonLazy1() {}

    public static SingletonLazy1 getInstance() {
        if (singleton == null) {
            singleton = new SingletonLazy1();
        }
        return singleton;
    }
}

类型: 懒汉式,延迟到调用方法时再创建
原理: 通过方法中判断非空进行控制.
缺点: 线程不安全,并发会产生多个实例,实际开发不能使用,已经不属于单例模式,这是个错误示范

线程安全的懒加载
class SingletonLazy2 {

    private volatile static SingletonLazy2 singleton;

    private SingletonLazy2() {}

    public static synchronized SingletonLazy2 getInstance() {
        if (singleton == null) {
            singleton = new SingletonLazy2();
        }
        return singleton;
    }
}

类型: 懒汉式,延迟到调用方法时再创建
原理: 通过方法中判断非空进行控制.volatile 声明内存可见
缺点: 通过synchronized进行同步控制,但是粒度较大,会涉及锁升级.无锁->偏向锁->轻量锁->重量锁

双重检查

懒汉式-双重检查(推荐使用)
class SingletonLazy3 {

    private volatile static SingletonLazy3 singleton;

    private SingletonLazy3() {}

    public static SingletonLazy3 getInstance() {
        if (singleton == null) {
            synchronized (SingletonLazy3.class) {
                if (singleton == null) {
                    singleton = new SingletonLazy3();
                }
            }
        }
        return singleton;
    }
}

类型: 懒汉式-双重检查,延迟到调用方法时再创建,懒加载
原理: 通过方法中判断非空进行控制.volatile 声明内存可见
缺点: 无

静态内部类(推荐使用)

class SingletonLazy4{

    private SingletonLazy4(){}

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

类型: 懒汉式-静态内部类,延迟到调用方法时再创建,懒加载
原理: 通过类加载方式实现线程安全,因为类只会被加载一次,内部通过cas 实现线程安全,jvm级别控制
缺点: 无

枚举(推荐使用)

enum Singleton2 {
    INSTANCE();
    private SingletonType singletonType;

    Singleton2() {
        singletonType = new SingletonType();
    }

    public SingletonType getInstance() {
        return singletonType;
    }
}

类型: 枚举是天然的单例
原理: 每个枚举实例都是static final类型,所以只能被实例化一次,这样我们通过构造方法来保证其中代码也只能实例化一次.这样来控制线程安全
缺点: 无


本文借鉴尚硅谷Java设计模式,韩顺平图解java,传送门

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值