面试必问之单例模式,今天必须恶补一下,就拿它来吊打面试官!
单例模式有几种?
- 饿汉式(最常见)
- 懒汉式(最常见)
- 加锁的懒汉式
- 双重判断加锁的懒汉式
- 内部静态类是实现的懒汉式
- 使用枚举
共有六种方式。
其中在懒汉式基础上扩展的有两种。即:加锁的懒汉式及双重判断加锁的懒汉式;还有一种是使用内部类实现的。即:内部静态类的;最后一种是比较少见的。使用枚举的。
懒汉式的单例模式代码实例,如下图:
public class Singleton{
//由于太懒 先不新建对象
public static Singleton singleton =null;
//构建私有的构造器,不让外部通过new创建对象
private Singleton(){
}
public static Singleton getInstance(){
//d等到使用的时候再新建对象
if(singleton == null){
singleton = new Singleton ;
}
return singleton;
}
}
懒汉式的优缺点:
优点:单例对象的生成是在应用需要使用单例对象时才去构造,可以提高应用的启动速度。
缺点:不是线程安全的,如果多个线程同时调用getlnstance方法,那么可能会生成多个单例对象。
适用场景:单例对象功能复杂,占用内存大,对应用的启动速度有要求
不适用:多线程同时使用
饿汉式的单例模式代码实例,如下图:
public class HungrySingleton{
由于太饿,上来就创建对象
public static HungrySingleton hungrySingleton =new HungrySingleton();
private HungrySingleton(){
}
//开放一个公有方法,判断是否已经存在实例,有返回,没有就新建一个再返回
pubic staic HungrySingleton getInstance(){
return hungrySingleton;
}
}
饿汉式的优缺点:
优点:简单方便
缺点:不管程序是否使用到了单例的对象,否会生成单例对象,并且由于静态对象在类加载时就生成,会降低应用的启动速度。
适用场景:类对象功能简单,占用内存较小,使用频繁。
不适用:类对象功能复杂,占用内存大,使用概率较低。
总结:
两种方案的构造函数和公用方法都是静态的(static),实例和构造函数又都是私有的(private)。
饿汉式每次调用的时候不用做创建,直接返回已经创建好的实例。这样虽然节省了时间,但是却占用了空间,实例本身为static的,会一直在内存中待着。
懒汉式则是判断,在用的时候才加载,会影响程序的速度。最关键的是,在并发的情况下,懒汉式是不安全的。如果两个线程,我们称它们为线程1和线程2,在同一时间调用getInstance()方法,如果线程1先进入if块,然后线程2进行控制,那么就会有两个实例被创建。