单例模式(singleton)

单例模式

   单例模式就是在系统运行期间有且只有一个实例,且只能提供私有的构造器,保证不能随意创建该类的实例。

第一种(饿汉模式)

package cn.smbms.test;

public class Singleton {
    //定义私有访问方法
    private Singleton() {}
    //获取实例
    private static Singleton singleton = new Singleton();
    //提供一个供外界访问该class的方法
    public static Singleton getInstance() {
        return singleton;
    }
}

  上述代码在类加载时就完成了初始化操作,故加载类较慢,但是获取对象的速度很快,也称饿汉模式,并且饿汉模式是在类初始化时就以及自行

实例化,因此不存在线程安全问题。

第二种(懒汉模式)

package cn.smbms.test;

public class Singleton {
    //定义私有访问方法
    private Singleton() {}
    //获取实例
    private static Singleton singleton;
    //提供一个供外界访问该class的方法
    public synchronized static Singleton getInstance() {
        if(singleton==null) {
            singleton= new Singleton();
        }
        return singleton;
    }
}
  上面第二中形式是lazy initialization, 也就是说第一次调用时初始Singleton,以后就不用再生成了。注意到lazy initialization 形式
中的synchronized,这个synchronized很重要,  如果没有synchronized,那么使用getInstance ()是有可能得到多个Singleton ,这种在
类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例,也称懒汉模式,即在调用方式时才获取实例。
  但在实际开发中,会遇到以下应用场景:
实例化单例类很消耗资源,我们希望可以要吃加载,即不想让它在类加载时就实例化,那如何处理呢?如下
package cn.smbms.test;

public class Singleton {
    //定义私有访问方法
    private Singleton() {}
    //获取实例
    private static Singleton singleton;
    public static class SingletionHelper{
        private static Singleton INSTANCE=new Singleton();
    } 
    public static Singleton getInstance() {
        singleton= SingletionHelper.INSTANCE;
        return singleton;
    }
    public static Singleton test() {
        return singleton;
    }
}

  上述中,同样利用了classloder的机制来保证初始化instance只有一个线程,但是跟之前的方式略有不同。按照之前的方式只要singleton类被装载了

,那么singleton就会被实例化,并没有达到lazy loading的效果。而现在这种静态内部的方式时:singleton被装载了,却不一定被初始化原因在于没有主

动调用getInstance()方法。

 小结

  • 懒汉:类加载时不创建实例,因此类加载速度快,但运行速度较慢,具备延迟加载的特性,但是又不存在线程安全问题
  • 饿汉:类加载时完成初始化,所以类加载慢,但获取对象速度快
  • 懒汉是“时间换空间”,饿汉就是“空间换时间”
原文地址:https://www.cnblogs.com/hfx123/p/9749894.html