Interview100-72 Singleton模式的几种实现方法

主要思想

单例模式属于常见设计模式中的一种,且应用较多,它主要是使一个类的实例数量保持一个,主要实现的思想为:将该类的构造方法设为私有,外部无法直接使用该类的构造函数进行实例化这个类的对象。外部类只能使用该类提供的静态方法创建该类的实例对象。在该静态方法中,通过对该类的实例对象进行存在性判断,若已经存在则直接返回该实例对象,若不存在,则通过调用私有构造函数进行创建后并返回。它具有多种实现方式。

常见写法1:饿汉式

public class Singleton {
    private final static Singleton INSTANCE = new Singleton();

    private Singleton() {}

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

这种为较为常见的一种写法,其中遵循将构造函数设置为私有方法。并且将唯一一个实例对象设置为静态常变量类型。这种方式,使得该类的唯一一个实例对象在类装载的时候就完成了实例化。这样可以避免多线程同步的问题,缺点则是没有实现懒加载(lacy loading),如果该类的实例一直没有使用到,则实例化的对象造成内存浪费。

常见写法2:懒汉式

public class Singleton {
    private static Singleton INSTANCE;

    private Singleton() {}

    public static Singleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

 这种方式最大的问题就是线程不安全,无法在多线程的情况下使用。但该中方式起到了一定的lazy loading的效果,如果是单线程环境下,还是可以使用。

线程同步优化懒汉式

public class Singleton {
    private static Singleton INSTANCE;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

由于最初版本的懒汉式线程不安全,这里使用同步方法的方式保证线程安全。但这种方式的问题是执行效率太低。

同步方式两次检查

public class Singleton {
    private static volatile Singleton INSTANCE;

    private Singleton() {}

    public static Singleton getInstance() {
        if (INSTANCE == null) {
            synchronized (Singletion.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton();
                }
            }
        }
        return INSTANCE;
    }
}

这种方式与上述同步方式的不同在于,在getInstance方法中进行了两次的check instance是否为null,第一重的check,保证了在多线程的情况下,当第一个线程同步的方式使用getInstance时已经创建了INSATNCE的实例,然后当第二个线程调用getInstance方法时,依然可以直接返回INSTANCE实例,同时保证了线程安全。

推荐使用:静态内部类

public class Singleton {
    private Singleton() {}

    static class SingletonInstance {
        private final static Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

 该方式与第一种饿汉式的方式相类似,对INSTANCE的限制都是使用静态常变量的方式。但与第一种方式不同的是,第一种方式的静态常变量在类加载的时候就完成了实例化。而这种方式,通过将静态常变量放置到一个静态内部类中,保证了不会再外部类状态时进行对象实例化,从而只有在调用getInstance方法时才会进行对象的实例化,保证了lazy loading的机制。同时静态内部类的设置保证了线程安全和高效率。因此推荐使用。

内容参考:https://www.cnblogs.com/zhaoyan001/p/6365064.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值