单例模式

1. 概念
  1. 广义单例模式,就是在jvm中,共用一个类的唯一实例
  2. 狭义单例模式,即单例类,通过类本身去实现上述目的
2. 优缺点
优点
  1. 避免频繁的创建和销毁实例,这点对大对象犹为重要
缺点
  1. 单例类较难扩展,牵一发而动全身
  2. 单例类不能被继承,因为构造器私有
3. 应用
  1. 线程池、缓存、日志、配置文件、打印机/显卡等硬件设备的驱动程序对象等等
  2. Servlet、Spring、Strust2、SpringMVC、线程池等
4. 创建单例类
1. 饿汉式(推荐)

网上都说饿汉式在不用时浪费内存,扯蛋!实例是在类加载时的准备阶段分配内存的,你不用时,根本不会触发它的加载!

public class SingletonClass1 {

    private static final SingletonClass1 INSTANCE = new SingletonClass1();

    private SingletonClass1() {
    }

    public static SingletonClass1 getInstance() {
        return INSTANCE;
    }
}

简单安全,实例在类加载时创建,而虚拟机保证类加载时线程安全。

2. 懒汉式

线程不安全,基本不用

public class SingletonClass2 {

    private static SingletonClass2 instance;

    private SingletonClass2() {}

    public static SingletonClass2 getInstance() {
        if (instance == null) {
            instance = new SingletonClass2();
        }
        return instance;
    }
}
3. 懒汉式-同步方法

线程安全,但效率低

public class SingletonClass3 {

    private static SingletonClass3 instance;

    private SingletonClass3() {}

    public static synchronized SingletonClass3 getInstance() {
        if (instance == null) {
            instance = new SingletonClass3();
        }
        return instance;
    }
}
4. 懒汉式-双重检测-同步代码块(可用)

线程安全,延迟加载,效率高

public class SingletonClass4 {

    private static SingletonClass4 instance;

    private SingletonClass4() {
    }

    public static SingletonClass4 getInstance() {
        if (instance == null) {
            synchronized (SingletonClass4.class) {
                if (instance == null) {
                    instance = new SingletonClass4(); // 1
                }
            }
        }
        return instance;
    }
}
  1. 这种双重检测机制是有问题的,问题出在//1,由所谓的无序写入造成的。一般来讲,当初始化一个对象的时候,会经历内存分配、初始化、返回对象在堆上的引用等一系列操作,这种方式产生的对象是一个完整的对象,可以正常使用。但是JAVA的无序写入可能会造成顺序的颠倒,即内存分配、返回对象引用、初始化的顺序,这种情况下对应到//1就是singleton已经不是null,而是指向了堆上的一个对象,但是该对象却还没有完成初始化动作。当后续的线程发现singleton不是null而直接使用的时候,就会出现意料之外的问题。
  2. JDK1.5之后,可以使用volatile关键字修饰变量来解决无序写入产生的问题,因为volatile关键字的一个重要作用是禁止指令重排序,即保证不会出现内存分配、返回对象引用、初始化这样的顺序,从而使得双重检测真正发挥作用。
  3. synchronized也可以保证有序性,但不会禁止指令重排,所以synchronized内部改变的变量,被其它线程在外面使用,是有安全问题的
5. 静态内部类(可用)

线程安全、延迟加载、效率高

public class SingletonClass5 {

    private static class InnerClass {
        private static final SingletonClass5 INSTANCE = new SingletonClass5();
    }

    public static SingletonClass5 getInstance() {
        return InnerClass.INSTANCE;
    }
}
6. 枚举类(可用)

线程安全、效率高、防反射

public enum SingletonClass6 {

    INSTANCE;

    SingletonClass6() {
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值