设计模式--单例设计模式

140 阅读2分钟

本文介绍了单例设计模式的饿汉式、懒汉式、双重锁、静态内存写法。

一、饿汉式

public class SingleTon {    // 1.私有化构造方法    private SingleTon() {}    // 2.私有的静态的当前类属性    private static SingleTon instance = new SingleTon();    // 3.公共的获取当前类属性的方法    public static SingleTon getInstance() {        return instance;    }}


优点:不会出现第一次使用对象时,出现延迟的情况,响应速度快,线程安全。

缺点:不管单例对象是否被使用,只要类一加载就创建,增加了内存的压力。

二、懒汉式

public class SingleTon {    // 1.私有构造方法    private SingleTon() {}    // 2.私有的静态的当前类类型的属性    private volatile static SingleTon instance;    // 3.公共的静态的获取当前类对象的方法    public static SingleTon getInstance() {        if(null == instance) {            instance = new SingleTon();        }        return instance;    }}

优点:对象需要使用时才创建,减轻了内存的压力。

缺点:第一次使用单例对象时,会出现一点延迟,线程非安全。

三、双重判断(懒汉式的升级版)

public class SingleTon {    // 1.私有构造方法    private SingleTon() {}    // 2.私有的静态的当前类类型的属性    private static volatile SingleTon instance;    // 3.公共的静态的获取当前类对象的方法    public static SingleTon getInstance() {        // 双重校验的目的在于提高方法的执行效率        if(null == instance) {            synchronized (SingleTon.class) {                if(null == instance) {                    instance = new SingleTon();                }            }        }        return instance;    }}

volatile关键字的作用:防止创建单例对象指令的重排序,创建对象可以分为三步步骤:①开辟一块堆内存空间②创建对象③将堆内存地址赋值给栈内存中的局部变量引用。所谓的指令重排序就是①②③的执行顺序会变成①③②,这就会出现单例对象还未创建,但是局部变量已经有引用了,这时局部变量进行后续操作都是错误的。

为什么会有指令的重排序呢?

因为指令的重排序可以提高程序的执行效率,所以在JVM中默认会对指令进行重排序,而有些情况我们不希望指令进行重排序,这时就需要使用到volatile关键字来防止指令的重排序。

优点:对象需要使用时,才创建,减轻了内存的压力,线程安全。

缺点:第一次使用单例对象时,会出现一点延迟。

四、静态内部类

public class SingleTon {    // 1.私有构造方法    private SingleTon() {}    // 2.静态内部类    static class Inner {        private static SingleTon instance = new SingleTon();    }    // 3.公共的静态的获取当前类对象的方法    public static SingleTon getInstance() {        return Inner.instance;    }}

优点:内存压力小,线程安全,写法更加优雅。

缺点:稍稍复杂。