单例设计模式(饿汉式VS懒汉式)
什么是单例模式 单例(单个的实例) 1.所谓单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法 2.单例设计模式有两种方式:饿汉式 与 懒汉式
饿汉式: 饿汉式听名字就知道它就像一个饿死鬼一样,有饭就赶紧吃,有饭就抢着吃。 所以,在程序启动或单例模式类被加载的时候,单例模式实例就已经被创建。
创建步骤: 1)构造器私有化 —>防止直接new对象 2)类的内部创建对象 3)向外暴露一个静态的公共方法 (getInstance)
//饿汉式 public class SingletonTest { //私有化类的构造器,让外部无法调用 private SingletonTest(){ } //类的内部创建类的对象,并且此对象必须声明静态 private static SingletonTest instance= new SingletonTest(); //提供公共的静态的方法,返回类的对象 public static SingletonTest getInstance(){ return instance; } }
懒汉式: 懒汉式顾名思义就像一个懒惰的大汉,能不干活就不干活。所以它直到第一次去使用的时候,才会创建实例对象。
实现步骤: 1.仍然构造器私有化 2.定义一个 static 静态属性对象 3.提供一个 public 的 static 方法,可以返回一个对象 4.懒汉式,只有当用户使用 getInstance 时,才返回对象, 后面再次调用时,会返回上次创建的对象
线程不安全模式
class Singleton{ //私有化类的构造器 private Singleton(){ } //声明当前类的对象,并且是static,但是没有赋值 private static Singleton instance = null; //声明为public、static的方法用来返回类的实例 //如果发现当且instance为null,给instance创建一个实例。 public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
线程安全模式:
class Singleton{ //私有化类的构造器 private Singleton(){ } //声明当前类的对象,并且是static,但是没有赋值 //此处添加volatile是为了防止指令重排序 private static volatile Singleton instance = null; //声明为public、static的方法用来返回类的实例 //如果发现当且instance为null,给instance创建一个实例。 public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ if(instance == null){ //这并不是一个原子操作 //1.给instance分配内存空间 //2.调用Singleton构造函数初始化 //3.将instance对象指向分配的内存空间,此时instance不为null //使用volatile修饰instance就是防止这1-2-3步被指令重排,保证其顺序执行 instance = new Singleton(); } } } return instance; } }
简简单单的总结一下吧 1.二者最主要的区别在于创建对象时机不同: 1)饿汉式是在类加载就创建了对象 2)懒汉式是在使用时在会创建对象 2.饿汉式不存在线程安全问题,懒汉式存在线程安全问题 3.饿汉式存在浪费资源的可能,因为它是在类加载的时候就创建了对象吗, 如果我们不使用它,那不就浪费了。 懒汉式是在使用的时候才会创建,所以就不存在这个问题啦。
补充:在我们javaSE标准类中,java.lang.Runtime 就是经典的单例模式。