单例模式(Singleton Pattern)负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。也属于创建型模式。
直接代码实现:
一、饿汉式
packagecom.xing.design.singleton; /*** 单例模式* @author xing*/publicclassSingletonObj { //创建 SingletonObj 的一个对象privatestaticSingletonObjinstance=newSingletonObj(); //构造方法私有化privateSingletonObj(){} //对外提供访问入口,因为关闭了构造方法,所以只能从这个入口访问本类对象publicstaticSingletonObjgetInstance(){ returninstance; } //写个方法用来调用publicvoidtest() { System.out.println("单例模式实例化对象的测试方法。。。"); } }
测试:
packagecom.xing.design.singleton; publicclassSingletonDemo { publicstaticvoidmain(String[] args) { SingletonObjsingletonObj1=SingletonObj.getInstance(); singletonObj1.test(); //再来一个对比下hashCodeSingletonObjsingletonObj2=SingletonObj.getInstance(); singletonObj2.test(); System.out.println("singletonObj1=>"+singletonObj1.hashCode()); System.out.println("singletonObj2=>"+singletonObj2.hashCode()); } }
结果:
可以看到两次获取的对象hashCode码一样,是同一个对象哈。
上述这种写法是在类加载的时候就实例化了对象,这种写法叫饿汉式。但是如果这个对象一直没有用,就造成了内存浪费,没有达到懒加载(Lazy Loading)的效果。
我理解的懒汉式和饿汉式:
懒汉式是用的时候再实例化,饿了再做饭。或者有句话叫啥来着,想蹲坑了才修厕所呢,哈哈哈
饿汉式是先实例化,用的时候直接取用。就跟饿过的人一样,先把饭做好,饿了就能吃。
二、懒汉式
packagecom.xing.design.singleton; /*** 单例模式* @author xing*/publicclassSingletonObj2 { //创建 SingletonObj 的一个对象privatestaticSingletonObj2instance; //构造方法私有化privateSingletonObj2(){ System.out.println("构造个SingletonObj2"); } //对外提供访问入口,因为关闭了构造方法,所以只能从这个入口访问本类对象publicstaticSingletonObj2getInstance(){ if(instance==null) { instance=newSingletonObj2(); } returninstance; } publicvoidtest() { System.out.println("单例模式实例化对象的测试方法。。。"); } }
测试:
packagecom.xing.design.singleton; publicclassSingletonDemo { publicstaticvoidmain(String[] args) { SingletonObj2singletonObj21=SingletonObj2.getInstance(); singletonObj21.test(); //再来一个对比下hashCodeSingletonObj2singletonObj22=SingletonObj2.getInstance(); singletonObj22.test(); System.out.println("singletonObj21=>"+singletonObj21.hashCode()); System.out.println("singletonObj22=>"+singletonObj22.hashCode()); } }
结果:
这种写法起到了Lazy Loading的效果,不过main方法调用的时候都是第一次加载类哈,看不出来,不过倒是能看出来获取两个实例对象只调用过一次构造哈,更能说明单例模式多次返回的都是同一个对象。
三、双重检验管控的线程安全单例模式
packagecom.xing.design.singleton; /*** 懒汉模式-线程安全,适用于多线程*/publicclassSingletonObj3{ privatestaticvolatileSingletonObj3safeSingleton;//防止指令重排privateSingletonObj3() { System.out.println("构造个SingletonObj3"); } publicstaticSingletonObj3getInstance(){ if(safeSingleton==null){ synchronized (SingletonObj3.class){ if(safeSingleton==null){//双重检测safeSingleton=newSingletonObj3(); } } } returnsafeSingleton; } publicvoidtest() { System.out.println("单例模式实例化对象的测试方法。。。"); } }
测试及结果:
重排序是为了优化性能,但是不管怎么重排序,在单线程下一定能保证结果的正确性,但是在多线程环境下,可能发生重排序,影响结果。具体底层的我也不懂,以后再学吧。这里要禁用重排序,就用了volatile 关键字。
总结:
单例模式只能由自己创建并始终只有一个实例化对象,核心代码是构造方法私有化、提供一个静态方法作为唯一访问入口。
应用场景有:当前系统登录人数管理、Java的Runtime、线程池等频繁的创建和销毁对象的情况。
END