最近在学习设计模式,在看到单例模式的时候,我一开始以为直接很了解单例模式了,实现起来也很简单,但是实际上单例模式有着好几个变种,并且多线程中涉及到线程安全问题,那么本文我们就来好好聊聊单例模式,说一下经典三种实现方式:饿汉式,懒汉式,登记式。并且解决掉多线程中可能出现的线程安全问题。
<强> 1。为什么要使用单例模式? 强>
在我们日常的工作中,很多对象通常占用非常重要的系统资源,比如:IO处理,数据库操作等,那我们必须要限制这些对象只有且始终使用一个公用的实例,即单例。
<强> 2。单例模式的实现方式强>
构造函数私有化,防止其他类生成唯一公用实例外的实例。且单例类应该被定义为决赛,也就是说单例类不能被继承,因为如果允许继承那子类就都可以创建实例,违背了类唯一实例的初衷。
类中一个静态变量来保存单实例的引用。
一个共有的静态方法来获取单实例的引用。
<强> 3。单例模式的UML类图强>
<>强4。单例模式的经典实现方式强>
-
<李>饿汉式:一开始就创建好实例,每次调用直接返回,经典的“拿空间换时间”。李>
<李>懒汉式:延迟加载,第一次调用的时候才加载,然后返回,以后的每次的调用就直接返回。经典”拿时间换空间”,多线程环境下要注意解决线程安全的问题。李>
<李>登记式:对一组单例模式进行的维护,主要是在数量上的扩展,通过线程安全的地图把单例存进的去,这样在调用时,先判断该单例是否已经创建,是的话直接返回,不是的话创建一个登记到地图中,再返回。李>
<强> 1。单例类强>
包com.hafiz.designPattern.singleton;/* * *描述:单例模式,饿汉式 *由hafiz.zhang> 公开课DesignPatternTest { @Test 公共空间testSingleton1 () { System.out.println(“- - - - - - - - - - - - - - - - - -测试饿汉式单例模式开始- - - - - - - - - - - - - - - -”); Singleton1 instance1=Singleton1.getInstance (); System.out.println(“第二次获取实例”); Singleton1 instance2=Singleton1.getInstance (); System.out.println (“instance1和instance2是否为同一实例& # 63;”+ (instance1==instance2)); System.out.println(“- - - - - - - - - - - - - - - - - -测试饿汉式单例模式结束- - - - - - - - - - - - - - - -”); } }
<强> 3。测试结果强>
<强> 1。单例类强>
包com.hafiz.designPattern.singleton;/* * *描述:单例模式——懒汉式 *由hafiz.zhang> 公开课DesignPatternTest { @Test 公共空间testSingleton2 () { System.out.println(“- - - - - - - - - - - - - - - - - -测试懒汉式单例模式开始- - - - - - - - - - - - - - - -”); Singleton2 instance1=Singleton2.getInstance (); System.out.println(“第二次获取实例”); Singleton2 instance2=Singleton2.getInstance (); System.out.println (“instance1和instance2是否为同一实例& # 63;”+ (instance1==instance2)); System.out.println(“- - - - - - - - - - - - - - - - - -测试懒汉式单例模式结束- - - - - - - - - - - - - - - -”); } }
<强> 3。测试结果强>
细心的同学已经发现,这种实现方式,在多线程的环境中,是有线程安全安全问题的,有可能两个或多个线程判断实例都为null,然后创建了好几遍实例,不符合单例的思想,我们可以对它进行改进。
原理:使用JDK的同步同步代码块来解决懒汉式线程安全问题。
<强> 1。单例类强>
包com.hafiz.designPattern.singleton;/* * *描述:单例模式——懒汉式 *由哈菲兹。张alt="你真的了解java单例模式了吗? ">
原理:使JVM用隐含的同步和类级内部类来解决,JVM隐含的同步解决了多线程情况下线程安全的问题,类级内部类解决只有使用的时候才加载(延迟加载)的问题。
你真的了解java单例模式了吗?