单例模式
Posted linbq1911
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。
1.定义:保证一个类仅有一个实例,并提供一个全局访问点。
2.类型:创建型
3.适用场景:想确保任何情况下都绝对只有一个实例。
4.优点:在内存里只有一个实例,减少了内存开销;
可以避免对资源的多重占用;
设置全局访问点,严格控制访问。
5.缺点:没有接口,扩展困难
6.重点:私有构造器、线程安全、延迟加载、序列化和反序列化安全、反射
7.实用技能:反编译、内存原理、多线程Debug
8.相关设计模式:工厂模式、享元模式
9.实例目录package
10.实例UML类图
11.代码
1 package com.geely.design.pattern.creational.singleton; 2 3 import java.io.Serializable; 4 5 public class HungrySingleton implements Serializable,Cloneable { 6 private final static HungrySingleton hungrySingleton; 7 static{ 8 hungrySingleton = new HungrySingleton(); 9 } 10 private HungrySingleton(){ 11 if(hungrySingleton != null){ 12 throw new RuntimeException("单例构造器禁止反射调用"); 13 } 14 } 15 public static HungrySingleton getInstance(){ 16 return hungrySingleton; 17 } 18 19 private Object readResolve(){ 20 return hungrySingleton; 21 } 22 23 @Override 24 protected Object clone() throws CloneNotSupportedException { 25 return getInstance(); 26 } 27 }
1 package com.geely.design.pattern.creational.singleton; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.Field; 5 6 public class LazySingleton { 7 private static LazySingleton lazySingleton = null; 8 private static boolean flag = true; 9 private LazySingleton(){ 10 if(flag){ 11 flag = false; 12 }else{ 13 throw new RuntimeException("单例构造器禁止反射调用"); 14 } 15 /*if(lazySingleton != null){ 16 throw new RuntimeException("单例构造器禁止反射调用"); 17 }*/ 18 } 19 public synchronized static LazySingleton getInstance(){ 20 //synchronized(LazySingleton.class){ 21 if(lazySingleton == null){ 22 lazySingleton = new LazySingleton(); 23 } 24 // } 25 return lazySingleton; 26 } 27 28 public static void main(String[] args) throws Exception{ 29 Class objectClass = LazySingleton.class; 30 //Class.forName(HungrySingleton.class.getName()); 31 Constructor constructor = objectClass.getDeclaredConstructor(); 32 constructor.setAccessible(true); 33 34 LazySingleton instance = LazySingleton.getInstance(); 35 Field flag = instance.getClass().getDeclaredField("flag"); 36 flag.setAccessible(true); 37 flag.set(instance,true); 38 LazySingleton newInstance = (LazySingleton) constructor.newInstance(); 39 40 System.out.println(instance); 41 System.out.println(newInstance); 42 System.out.println(instance == newInstance); 43 } 44 }
1 package com.geely.design.pattern.creational.singleton; 2 3 public class LazyDoubleCheckSingleton { 4 private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null; 5 private LazyDoubleCheckSingleton(){ 6 7 } 8 public static LazyDoubleCheckSingleton getInstance(){ 9 if(lazyDoubleCheckSingleton == null){ 10 synchronized (LazyDoubleCheckSingleton.class){ 11 if(lazyDoubleCheckSingleton == null){ 12 lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton(); 13 //1.分配内存给这个对象 14 //2.初始化对象 15 //3.设置lazyDoubleCheckSingleton指向刚分配的内存地址 16 // intra-thread semantics 17 //2和3可能调换顺序 18 } 19 } 20 } 21 return lazyDoubleCheckSingleton; 22 } 23 }
1 package com.geely.design.pattern.creational.singleton; 2 3 public class StaticInnerClassSingleton { 4 private static class InnerClass{ 5 private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton(); 6 } 7 public static StaticInnerClassSingleton getInstance(){ 8 return InnerClass.staticInnerClassSingleton; 9 } 10 11 private StaticInnerClassSingleton(){ 12 if(InnerClass.staticInnerClassSingleton != null){ 13 throw new RuntimeException("单例构造器禁止反射调用"); 14 } 15 } 16 }
1 package com.geely.design.pattern.creational.singleton; 2 3 import org.apache.commons.lang.StringUtils; 4 5 import java.util.HashMap; 6 import java.util.Map; 7 8 public class ContainerSingleton { 9 private ContainerSingleton(){} 10 private static Map<String, Object> singletonMap = new HashMap<>(); 11 12 public static void putInstance(String key,Object instance){ 13 if(StringUtils.isNotBlank(key) && instance != null){ 14 if(!singletonMap.containsKey(key)){ 15 singletonMap.put(key,instance); 16 } 17 } 18 } 19 public static Object getInstance(String key){ 20 return singletonMap.get(key); 21 } 22 23 }
1 package com.geely.design.pattern.creational.singleton; 2 3 public class ThreadLocalInstance { 4 private static final ThreadLocal<ThreadLocalInstance> threadLocalInstanceThreadLocal 5 = new ThreadLocal<ThreadLocalInstance>(){ 6 @Override 7 protected ThreadLocalInstance initialValue() { 8 return new ThreadLocalInstance(); 9 } 10 }; 11 12 private ThreadLocalInstance(){} 13 public static ThreadLocalInstance getInstance(){ 14 return threadLocalInstanceThreadLocal.get(); 15 } 16 17 }
1 package com.geely.design.pattern.creational.singleton; 2 3 public enum EnumInstance{ 4 INSTANCE{ 5 protected void printTest(){ 6 System.out.println("Geely Print Test"); 7 } 8 }; 9 protected abstract void printTest(); 10 private Object data; 11 12 public Object getData() { 13 return data; 14 } 15 16 public void setData(Object data) { 17 this.data = data; 18 } 19 public static EnumInstance getInstance(){ 20 return INSTANCE; 21 } 22 }
1 package com.geely.design.pattern.creational.singleton; 2 3 public class T implements Runnable { 4 @Override 5 public void run() { 6 //LazySingleton instance = LazySingleton.getInstanc(); 7 //LazyDoubleCheckSingleton instance = LazyDoubleCheckSingleton.getInstance(); 8 //StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance(); 9 //ContainerSingleton.putInstance("object",new Object()); 10 //Object instance = ContainerSingleton.getInstance("object"); 11 ThreadLocalInstance instance = ThreadLocalInstance.getInstance(); 12 System.out.println(Thread.currentThread().getName() + ": "+instance); 13 } 14 }
1 package com.geely.design.pattern.creational.singleton; 2 3 import java.io.*; 4 import java.lang.reflect.Constructor; 5 import java.lang.reflect.Method; 6 7 public class Test { 8 public static void main(String[] args) throws Exception { 9 //LazySingleton lazySingleton = LazySingleton.getInstanc(); 10 //System.out.println(lazySingleton); 11 12 /*Thread t1 = new Thread(new T()); 13 Thread t2 = new Thread(new T()); 14 t1.start(); 15 t2.start();*/ 16 17 // HungrySingleton instance = HungrySingleton.getInstance(); 18 // ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file")); 19 // oos.writeObject(instance); 20 // File file = new File("singleton_file"); 21 // ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); 22 // HungrySingleton newInstance = (HungrySingleton)ois.readObject(); 23 // System.out.println(instance); 24 // System.out.println(newInstance); 25 // System.out.println(instance == newInstance); 26 27 // Class objectClass = HungrySingleton.class; 28 // //Class.forName(HungrySingleton.class.getName()); 29 // Constructor constructor = objectClass.getDeclaredConstructor(); 30 // constructor.setAccessible(true); 31 // HungrySingleton instance = HungrySingleton.getInstance(); 32 // HungrySingleton newInstance = (HungrySingleton) constructor.newInstance(); 33 // System.out.println(instance); 34 // System.out.println(newInstance); 35 // System.out.println(instance == newInstance); 36 37 // Class objectClass = StaticInnerClassSingleton.class; 38 // //Class.forName(HungrySingleton.class.getName()); 39 // Constructor constructor = objectClass.getDeclaredConstructor(); 40 // constructor.setAccessible(true); 41 // StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance(); 42 // StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance(); 43 // System.out.println(instance); 44 // System.out.println(newInstance); 45 // System.out.println(instance == newInstance); 46 47 // Class objectClass = LazySingleton.class; 48 // //Class.forName(HungrySingleton.class.getName()); 49 // Constructor constructor = objectClass.getDeclaredConstructor(); 50 // constructor.setAccessible(true); 51 // LazySingleton newInstance = (LazySingleton) constructor.newInstance(); 52 // LazySingleton instance = LazySingleton.getInstance(); 53 // 54 // System.out.println(instance); 55 // System.out.println(newInstance); 56 // System.out.println(instance == newInstance); 57 58 // EnumInstance instance = EnumInstance.getInstance(); 59 // instance.setData(new Object()); 60 // ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file")); 61 // oos.writeObject(instance); 62 // File file = new File("singleton_file"); 63 // ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); 64 // EnumInstance newInstance = (EnumInstance)ois.readObject(); 65 // System.out.println(instance.getData()); 66 // System.out.println(newInstance.getData()); 67 // System.out.println(instance.getData() == newInstance.getData()); 68 69 // Class objectClass = EnumInstance.class; 70 // //Class.forName(HungrySingleton.class.getName()); 71 // Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class); 72 // constructor.setAccessible(true); 73 // EnumInstance newInstance = (EnumInstance) constructor.newInstance("Geely",666); 74 // EnumInstance instance = EnumInstance.getInstance(); 75 // System.out.println(instance); 76 // System.out.println(newInstance); 77 // System.out.println(instance == newInstance); 78 79 // EnumInstance instance = EnumInstance.getInstance(); 80 // instance.printTest(); 81 82 HungrySingleton hungrySingleton = HungrySingleton.getInstance(); 83 Method method = hungrySingleton.getClass().getDeclaredMethod("clone"); 84 method.setAccessible(true); 85 HungrySingleton cloneHungrySingletion = (HungrySingleton)method.invoke(hungrySingleton); 86 System.out.println(hungrySingleton); 87 System.out.println(cloneHungrySingletion); 88 System.out.println("program end"); 89 } 90 }
以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章