单例:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
1.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
2.当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
优点:
由于单例模式只生成一个实例,减少了系统性能开销,当一个对象
的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过
在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决
单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计
一个单例类,负责所有数据表的映射处理
常见的五种单例实现方式:
主要:
饿汉式(线程安全,调用效率高,但是,不能延时加载)也就是按需加载
懒汉式(线程安全,调用效率不高,但是,可以延时加载)//加了同步锁
其他:
双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题,不建议使用)
//在if(){}判断为空之后的代码加同步代码块,两层同步代码块
静态内部类式(线程安全,调用效率高 延时加载)
要点:
外部类没有static属性,不会像饿汉式那样立即加载对象
只有真正调用getInstance()才会加载静态内部类加载类时线程是安全的,
instance是static final类型,保证了内存中只有这一个实例存在,而且只能
被赋值一次,从而保证了线程的安全性
兼备了并发搞笑调用和延迟加载的优势
package com.luruixiao.pattern.singleton; /* * 外部类没有static属性,不会像饿汉式那样立即加载对象 只有真正调用getInstance()才会加载静态内部类加载类时线程是安全的, instance是static final类型,保证了内存中只有这一个实例存在,而且只能 被赋值一次,从而保证了线程的安全性 兼备了并发搞笑调用和延迟加载的优势 */ public class SingletonDemo { private SingletonDemo(){ } private static class SingletonClassInstance{ private static final SingletonDemo instance = new SingletonDemo(); } public static SingletonDemo getInstance(){ return SingletonClassInstance.instance; } }
package com.luruixiao.pattern.singleton; import java.io.ObjectStreamException; import java.io.Serializable; public class SingletonDemo2 implements Serializable{ private static final long serialVersionUID = 1L; private static SingletonDemo2 s = new SingletonDemo2(); private SingletonDemo2(){ if(s!=null){//防止反射的调用 throw new RuntimeException(); } } public static SingletonDemo2 getInstance(){ return s; } //反序列化时,直接调用此方法,返回一个对象,而不是单独创建反序列化的新对象 private Object readResolve() throws ObjectStreamException{ return s; } }
枚举单例(线程安全,调用效率高,不能延时加载)
优点:
实现简单
枚举本身就是单例模式,由JVM从根本上提供而来保障,避免通过反射和反序列化的漏铜
缺点:
无延迟加载