package com.gof23.singleton; /** * 单例模式 * 核心作用:保证一个类只要一个对象,提供一个方法访问这个对象。 * 常见应用场景: * windows里面的任务管理器就是个单例 回收站也是 * 项目中的配置文件 * 网站的计数器 * 程序应用的日志 * 数据库的连接池 * 操作系统的文件系统 * Servlet中的Application对象也是单例 * servlet编程中,每个serv也是单例 * 在Spring中每个Bean默认也是单例的 这么做的原因是方便Spring容器管理 * springMVC框架/struts框架中,控制器的对象也是单例 * * 优点 * 减少系统性能开销 * 优化共享资源访问 * * 常见5种单例模式的实现方式: * 主要 * 懒汉式: 线程安全,效率不高、但可以延时加载。 * 饿汉式:线程不安全,效率高。但是,不能延时加载、 * 其他 * 双重检测锁式 :由于JVM底层内部模型的原因,偶尔出问题,不建议使用。 * 静态内部类式: 线程安全,效率高。还可 延时加载。 * 枚举单例 : 线程安全效率高 ,但不能延时加载。 */ public class SingleTonTest { public static void main(String[] args) { HungrySingleton s1 = HungrySingleton.getInstance(); LazySingleton s2 = LazySingleton.getInstance(); DoubleCheckLock s3 = DoubleCheckLock.getInstance(); StaticInnerClassesDemo s4 = StaticInnerClassesDemo.getInstance(); EnumDemo s5 = EnumDemo.INSTANCE; System.out.println(s1); System.out.println(s2); System.out.println(s3); System.out.println(s4); System.out.println(s5); } }
com.gof23.singleton.HungrySingleton@3fbefab0
com.gof23.singleton.LazySingleton@133c5982
com.gof23.singleton.DoubleCheckLock@5f186fab
com.gof23.singleton.StaticInnerClassesDemo@3d4b7453
INSTANCE
饿汉模式
package com.gof23.singleton; /** * 饿汗模式 * 饿汉式:线程不安全,效率高。但是,不能延时加载。 * 调用方法 * 直接返回一个对象 * @author Administrator * */ public class HungrySingleton { //静态属性 从属于类 这个属性 指向一个对象。 //加载类时,天然的线程是安全的。 类初始化式立即加载(没有延时加载,资源浪费。) private static final HungrySingleton hungrySingleton=new HungrySingleton();//提供一个属性 类初始化式立即加载 private HungrySingleton(){};//把构造器私有,别人访问不了。 //提供一个公开的方法 由于加载类时,天然的线程是安全的。 // 所以不加同步 synchronized 效率更高 public static /*synchronized*/ HungrySingleton getInstance(){ return hungrySingleton; } }
懒汉模式
package com.gof23.singleton; /** * 懒单例模式 * 先判断 再创建 * 懒汉式: 线程安全,效率不高、但可以延时加载。 * @author Administrator * */ public class LazySingleton { //类加载时 不初始化这个对象 (延时加载)真正用时再初始化对象 加载类是天然线程安全 private static LazySingleton lazySingleton=null; private LazySingleton(){};//私有构造器 //延时加载 懒加载 资源利用效率高 但每次调用 getInstanc()方法都要同步synchronized(避免并发高的时候多个线程创建多个对象) 并发效率比较低。 public synchronized static LazySingleton getInstance(){ //第一加载 判断 为空 创建对象 那么 第二次判断不为空 则立即返回对象 if(lazySingleton==null){ lazySingleton = new LazySingleton(); } return lazySingleton; } }
双重检测锁模式(不建议使用)
package com.gof23.singleton; /** * 双重检测锁式 :由于JVM底层内部模型的原因,偶尔出问题,不建议使用。 * * 综合了懒汉式和饿汉式的优点 * 但是由于底层JVM模式 不支持和编译器优化不好 所以不建议使用 * * 第一次的时候 同步 之后 直接返回对象 * @author Administrator * */ @Deprecated public class DoubleCheckLock { public static DoubleCheckLock doubleCheckLock=null; public static DoubleCheckLock getInstance(){ if(doubleCheckLock==null){ DoubleCheckLock sc; synchronized(DoubleCheckLock.class){ sc=doubleCheckLock; if(sc==null){ synchronized(DoubleCheckLock.class){ if(sc==null){ sc=new DoubleCheckLock(); } } doubleCheckLock = sc ; } } } return doubleCheckLock; } }
静态内部类模式
package com.gof23.singleton; /** * 静态内部类式: 线程安全,效率高。还可 延时加载。 * * @author Administrator * */ public class StaticInnerClassesDemo { //加载 class StaticInnerClassesDemo这个类型 并不会立刻加载静态内部类private static class StaticInnerClasses //而是当你真正加载时 调用getInstance()方法时 才加载静态内部类 private static class StaticInnerClasses { private static final StaticInnerClassesDemo staticInnerClasses= new StaticInnerClassesDemo(); } //提供一个方法获取对象 public static StaticInnerClassesDemo getInstance(){ //通过类。方法 的方式 获得对象 return StaticInnerClasses.staticInnerClasses; } //构造器私有 private StaticInnerClassesDemo(){ } }
枚举单例模式
package com.gof23.singleton; /** * 枚举单例 : 线程安全效率高 ,但不能延时加载 * * 避免了反射和反序列化的漏洞 * 没有延时加载 * @author Administrator * */ public enum EnumDemo { //这个枚举元素本身就是单例对象 INSTANCE; //添加自己需要的操作 public void singletonOperation(){ } }
单例模式三要素
1. 构造方法私有化
2. 静态属性指向实例
3. public static的 getInstance方法,返回第二步的静态属性