之前只知道单例模式有两种:懒汉式和饿汉式,后来因为看到一句话,如果你将构造函数私有化,别人使用反射,这个时候怎么办,所以就知道了第三种方式枚举模式。然后今天又看到了静态内部类式和双重检测锁,今天就总结一下。
一、单例模式
(1)核心:保证只有一个实例,并提供一个访问全局的访问点。
(2)使用场景:
Windows的任务管理器
.Windows的回收站
项目中读取配置文件,没有必要每次都进行读取。
网站计数器
日志管理
数据库连接池,等等
(3)优点
使用单例只生成一个对象,减少系统的开销,对于一个对象产生需要比较多的资源,如配置、产生依赖对象时,我们可以使用单例对象
单例模式可以设置全局的访问点,共享资源的访问。
2.单例设计模式的实现方式
(1)饿汉式:线程安全,调用效率高,但是不延迟加载
a) 首先私有构造函数
b) 使用私有得静态变量创建一个方法
c) 提供一个静态的方法访问次对象
它是一个线程安全的的模式,对象不是自己来创建,而是有一个对象等待使用,不需要同步,效率高。
浪费资源,没有延迟加载。
实现方式:
package kw.test.sjms; /* * 单例模式 * 饿汉式单例模式 * */ public class DemoEH { private static DemoEH instance = new DemoEH(); private DemoEH() {} public static DemoEH getInstace() { return instance; } }
(2)懒汉式:线程安全,调用效率不高,但是,可以延迟加载
··· 使用的时候才去加载,但是需要使用synchronized
· ··· 资源利用率高,但是效率不是很高。
···缺点:每次都需要同步,浪费资源。
实现方式:
package kw.test.sjms; /* * 懒汉式单例模式 */ public class DemoLH { private static DemoLH instance ; private DemoLH(){} public synchronized static DemoLH getinstance(){ if(instance == null) { instance = new DemoLH(); } return instance; } }
(3) 双重检测锁式:由于JVM层底内部模型原因,偶尔会出现问题,不建议使用。
·解决了懒汉式的每次都需要锁判断的资源浪费。
·将锁放到if判断的内部,提高了效率,不需要每次都进行同步。
package kw.test.sjms; /* * 双重锁的单例模式 */ public class DemoSCS { private DemoSCS(){} private static DemoSCS instance = null ; public static DemoSCS getInstance() { if(instance == null) { DemoSCS demoSCS; synchronized (DemoSCS.class) { if(instance == null) { instance = new DemoSCS(); } } } return instance; } }
(4)静态内部类式:线程安全,调用效率高,但是可以延迟加载
·线程安全、效率高于懒汉式,并且有懒加载。
package kw.test.sjms; /* * 静态内部类 */ public class DemoJTNB { private static class createInstance { private static final DemoJTNB instance = new DemoJTNB(); } private DemoJTNB() { } public static DemoJTNB getInstance() { return createInstance.instance; } }
(5) 枚举单例:线程安全,调用效率高,不能延迟加载,可以防止反射创建。
·枚举是天然的单例。但是没有延迟加载的功能。
package kw.test.sjms; public enum DemoMJ { instace; public void getInstance() { } }
最好的模式:线程安全、调用效率高、要有懒加载。最完美的实现方式。