spring设计模式-单例模式
📅 2026/7/28 15:29:41
👁️ 阅读次数
📝 编程学习
单例模式
:是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式是创建型模式
- 懒汉式单例模式:在类加载的时候就立即初始化,并且创建为单例对象,它绝对线程安全,线程还没出现的时候就实例化了
- 不可能存在访问安全问题。
- 优点:没有加任何锁,执行效率比较高,用户体验比懒汉式单例模式更好
- 缺点:类加载的时候就初始化,不管用不用都占着空间,浪费了内存。
饿汉式: public class HungrySingleton { private static HungrySingleton hungrySingleton=new HungrySingleton(); //另一种写法 private static HungrySingleton hungrySingleton1; static{ hungrySingleton1=new HungrySingleton(); } private HungrySingleton(){} public static HungrySingleton getInstance(){ return hungrySingleton; } } 懒汉式: /** * 特点:被外部类调用的时候,内部类才会被加载.缺点:线程不安全 */ public class LazySingleton { private LazySingleton(){} private static LazySingleton lazySingleton=null; public static LazySingleton getInstance(){ if (lazySingleton==null){ lazySingleton=new LazySingleton(); } return lazySingleton; } //方法一:线程不安全的办法,加锁,缺点:性能下降 public static synchronized LazySingleton getInstance1(){ if (lazySingleton==null){ lazySingleton=new LazySingleton(); } return lazySingleton; } //方法二:双重检验所:解决线程安全和性能问题(双重检验锁) public static LazySingleton getInstance2(){ if(lazySingleton==null){ synchronized (LazySingleton.class){ if(lazySingleton==null){ lazySingleton=new LazySingleton(); //1、分配内存给这个对象 //2、初始化对象 //3、设置lazysingleton指向刚分配的内存地址 } } } return lazySingleton; } } 内部类: package com.wanda.singleton; import java.lang.reflect.Constructor; /** * 这种形式兼顾了饿汉式内存浪费问题和synchronized性能问题 */ public class LazyInnerSingleton { // private LazyInnerSingleton(){} //修改后的构造方法 private LazyInnerSingleton(){ if(LazyHolder.lazy!=null){ throw new RuntimeException("不允许创建多个实例"); } } public static final LazyInnerSingleton getInstance(){ return LazyHolder.lazy; } //内部类在方法调用之前初始化,避免了线程不安全的问题 private static class LazyHolder{ private static final LazyInnerSingleton lazy=new LazyInnerSingleton(); } public static void main(String[] args) { //反射破坏单例情况,通过这种方式会创建两个不同的单例。可以在构造方法中做一些限制,一旦多次重复创建就抛出异常。 try { Class<?> clazz=LazyInnerSingleton.class; Constructor constructor=clazz.getDeclaredConstructor(null); //强制访问 constructor.setAccessible(true); Object o1=constructor.newInstance(); Object o2=constructor.newInstance(); System.out.println(o1==o2); }catch (Exception e){ e.printStackTrace(); } } } 序列化破坏单例 package com.wanda.singleton; import java.io.*; //一个单例对象创建后,有时需要序列化到磁盘,下次使用时在从磁盘读入,进行反序列化,反序列华的对象会重新分配内存 //即重新创建,如果序列化的对象是单例,就违背了单例的意义。 public class SeriableSingleton implements Serializable { public static final SeriableSingleton INSTANCE=new SeriableSingleton(); private SeriableSingleton(){} public static SeriableSingleton getInstance(){ return INSTANCE; } private Object readResolve(){ return INSTANCE; } public static void main(String[] args) { SeriableSingleton s1=null; SeriableSingleton s2=SeriableSingleton.getInstance(); FileOutputStream fos=null; try { fos=new FileOutputStream("seriablesingleton.obj"); ObjectOutputStream os=new ObjectOutputStream(fos); os.writeObject(s2); os.flush(); os.close(); FileInputStream fis=new FileInputStream("seriablesingleton.obj"); ObjectInputStream ois=new ObjectInputStream(fis); s1=(SeriableSingleton) ois.readObject(); ois.close(); System.out.println(s1); System.out.println(s2); System.out.println(s1==s2);//false 解决方法:加上readResolve方法 }catch (Exception e){ } } } 枚举: package com.wanda.singleton; import java.io.*; //一个单例对象创建后,有时需要序列化到磁盘,下次使用时在从磁盘读入,进行反序列化,反序列华的对象会重新分配内存 //即重新创建,如果序列化的对象是单例,就违背了单例的意义。 public class SeriableSingleton implements Serializable { public static final SeriableSingleton INSTANCE=new SeriableSingleton(); private SeriableSingleton(){} public static SeriableSingleton getInstance(){ return INSTANCE; } private Object readResolve(){ return INSTANCE; } public static void main(String[] args) { SeriableSingleton s1=null; SeriableSingleton s2=SeriableSingleton.getInstance(); FileOutputStream fos=null; try { fos=new FileOutputStream("seriablesingleton.obj"); ObjectOutputStream os=new ObjectOutputStream(fos); os.writeObject(s2); os.flush(); os.close(); FileInputStream fis=new FileInputStream("seriablesingleton.obj"); ObjectInputStream ois=new ObjectInputStream(fis); s1=(SeriableSingleton) ois.readObject(); ois.close(); System.out.println(s1); System.out.println(s2); System.out.println(s1==s2);//false 解决方法:加上readResolve方法 }catch (Exception e){ } } } 容器式: package com.wanda.singleton; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 容器式单例模式:非线程安全 */ public class ContainerSingleton { private ContainerSingleton(){} private static Map<String,Object> map=new ConcurrentHashMap<>(); public static Object getBean(String clazzName){ synchronized (map){ if(!map.containsKey(clazzName)){ Object obj=null; try{ obj=Class.forName(clazzName).newInstance(); map.put(clazzName,obj); }catch (Exception e){ e.printStackTrace(); } return obj; }else{ return map.get(clazzName); } } } }
编程学习
技术分享
实战经验