设计模式 之 单例- 2019-10-10 20:40:40- 设计模式: java,编程,设计模式,单例
概念
保证一个类的实例全局只有一个,并提供一个全局访问点。
特性
构造私有化
实现方式 8种
饿汉式
优点:不会产生线程问题,保证唯一单例
缺点;如果不使用时就初始化,会导致无用对象占用系统资源
public class HungrySingleton {private static final HungrySingleton hungrySingleton = new HungrySingleton();/*** 构造私有化*/private HungrySingleton() {}public static HungrySingleton getInstance() {return hungrySingleton;}}public class HungrySingletonThread implements Runnable {@Overridepublic void run() {HungrySingleton instance = HungrySingleton.getInstance();System.out.println(instance);}}
懒汉式(线程安全/不安全)
线程不安全
* 优点:节省资源
* 缺点:有线程安全问题
public class LazySingleton {private static LazySingleton lazySingleton = null;private LazySingleton() {}public static LazySingleton getInstance() {if (null == lazySingleton) {lazySingleton = new LazySingleton();}return lazySingleton;}}public class LazySingletonTread implements Runnable {@Overridepublic void run() {LazySingleton laySingleton = LazySingleton.getInstance();System.out.println(laySingleton);}}
线程安全
* 优点:节省内存资源 无线程问题
* 缺点:性能下降 资源占用时间过长 ,会锁住整个类
public class LazySyncSingleton {private static LazySyncSingleton lazySingleton = null;private LazySyncSingleton() {}public static synchronized LazySyncSingleton getInstance() {if (null == lazySingleton) {lazySingleton = new LazySyncSingleton();}return lazySingleton;}}public class LazySyncSingletonTread implements Runnable {@Overridepublic void run() {LazySyncSingleton laySingleton = LazySyncSingleton.getInstance();System.out.println(laySingleton);}}
双重锁校验
public class LazyDoubleCheckSyncSingleton {private static LazyDoubleCheckSyncSingleton lazySingleton = null;private LazyDoubleCheckSyncSingleton() {}public static LazyDoubleCheckSyncSingleton getInstance() {//一层校验:为了提高性能。如果将synchronized锁在方法上或是判断条件上,当有一个线程获取到锁的时候,// 其他线程就会处于等待状态,进入不了内部逻辑。if (null == lazySingleton) {synchronized (LazyDoubleCheckSyncSingleton.class) {//第二层校验 防止两个线程同时满足了第一层校验,再做一次校验,防止多次创建if (null == lazySingleton) {lazySingleton = new LazyDoubleCheckSyncSingleton();}}}return lazySingleton;}}public class LazyDoubleCheckSyncSingletonTread implements Runnable {@Overridepublic void run() {LazyDoubleCheckSyncSingleton laySingleton = LazyDoubleCheckSyncSingleton.getInstance();System.out.println(laySingleton);}}
静态内部类
* 优点:性能最优。不需要使用线程,利用JVM加载静态内部类的机制保证多线程安全
* 懒汉式单例
* 缺点:
* 需要注意反射破坏单例的问题 解决:在构造中直接抛异常
* 需要注意序列化出现的问题 : 添加readResolve方法
public class InnerSingleton implements Serializable, Cloneable {// private static Boolean open = true;private InnerSingleton() {// TODO: 设置开关这种方式不行 因为私有属性也可以被反射重新赋值// if (open) {// synchronized (InnerSingleton.class) {// if (open) {// open = false;// }// }// } else {// throw new RuntimeException("不可实例化");// }//被实例化后 类就被加载到内存中,不会被重复加载if (null != InnerSingletonHandle.inner) {throw new RuntimeException("不可实例化");}}public static InnerSingleton getInstance() {return InnerSingletonHandle.inner;}private static class InnerSingletonHandle {private static final InnerSingleton inner = new InnerSingleton();}/*** 解决反射问题** @return*/public Object readResolve() {return InnerSingletonHandle.inner;}/*** 允许复制实例* @return* @throws CloneNotSupportedException*/@Overrideprotected Object clone() throws CloneNotSupportedException {return InnerSingletonHandle.inner;}}public class InnerSingletonTread implements Runnable {@Overridepublic void run() {InnerSingleton laySingleton = InnerSingleton.getInstance();System.out.println(laySingleton);}}
注册式单例:枚举
public enum RegisterSingleton {SINGLETON;private Object object;public void setObject(Object object) {this.object = object;}public Object getObject() {return object;}public static RegisterSingleton getInstance() {return SINGLETON;}}public class RegisterSingletonThread implements Runnable {@Overridepublic void run() {RegisterSingleton singleton = RegisterSingleton.SINGLETON;System.out.println(singleton);}}容器式单例public class ContainerSingleton {private ContainerSingleton() {}private static Map<String, Object> container = new HashMap<>();public static Object getBean(String className) {try {if (!container.containsKey(className)) {Object object = Class.forName(className).newInstance();container.put(className, object);return object;}} catch (Exception e) {e.printStackTrace();}return container.get(className);}}public class ContainerSingletonThread implements Runnable {@Overridepublic void run() {Object bean = ContainerSingleton.getBean("com.xy.blog.test.model.Person");System.out.println(bean);}}
ThreadLocal实现单例
测试
public class SingletonTest {/*** 饿汉单例*/@Testpublic void hungrySingletonTest() {Thread t1 = new Thread(new HungrySingletonThread());Thread t2 = new Thread(new HungrySingletonThread());t1.start();t2.start();System.out.println("end");}/*** 懒汉单例*/@Testpublic void lazySingletonTest() {Thread t1 = new Thread(new LazySingletonTread());Thread t2 = new Thread(new LazySingletonTread());t1.start();t2.start();System.out.println("end");}/*** 懒汉单例 :线程安全 线程锁 锁类*/@Testpublic void lazySyncSingletonTest() {Thread t1 = new Thread(new LazySyncSingletonTread());Thread t2 = new Thread(new LazySyncSingletonTread());t1.start();t2.start();System.out.println("end");}/*** 懒汉单例 : 方法锁 依旧线程不安全:单例被创建两次*/@Testpublic void lazySyncSingletonTest2() {Thread t1 = new Thread(new LazySyncSingletonTread2());Thread t2 = new Thread(new LazySyncSingletonTread2());t1.start();t2.start();System.out.println("end");}/*** 懒汉单例:双重锁校验*/@Testpublic void lazyDoubleCheckSyncSingletonTest() {Thread t1 = new Thread(new LazyDoubleCheckSyncSingletonTread());Thread t2 = new Thread(new LazyDoubleCheckSyncSingletonTread());t1.start();t2.start();try {Thread.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("end");}/*** 饿汉式 单例 静态内部类*/@Testpublic void innerSingletonTest() {try {Thread t1 = new Thread(new InnerSingletonTread());t1.start();Thread.sleep(1);reflect();Thread.sleep(1);System.out.println("end");} catch (InterruptedException e) {e.printStackTrace();}}/*** 反射暴力获取单例*/@Testpublic void reflect() {try {Class<InnerSingleton> innerSingletonClass = InnerSingleton.class;Constructor<InnerSingleton> declaredConstructor = innerSingletonClass.getDeclaredConstructor();declaredConstructor.setAccessible(true);Field open = innerSingletonClass.getDeclaredField("open");open.setAccessible(true);open.set(null, true);InnerSingleton innerSingleton = declaredConstructor.newInstance();System.out.println(innerSingleton);} catch (Exception e) {e.printStackTrace();}}/*** 序列化破坏单例*/@Testpublic void serializable() {InnerSingleton innerSingleton = InnerSingleton.getInstance();System.out.println(innerSingleton);InnerSingleton innerSingleton1 = JSONObject.parseObject(JSONObject.toJSONString(innerSingleton), InnerSingleton.class);System.out.println(innerSingleton1);try {//序列化FileOutputStream fileOutputStream = new FileOutputStream("temp");ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);objectOutputStream.writeObject(innerSingleton);//反序列化FileInputStream fileInputStream = new FileInputStream("temp");ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);InnerSingleton o = (InnerSingleton) objectInputStream.readObject();//打印结果System.out.println(innerSingleton == o);} catch (Exception e) {e.printStackTrace();}}@Testpublic void cloneDemo() {InnerSingleton innerSingleton = InnerSingleton.getInstance();try {InnerSingleton clone = (InnerSingleton) innerSingleton.clone();System.out.println(clone == innerSingleton);} catch (CloneNotSupportedException e) {e.printStackTrace();}}/*** 注册式单例*/@Testpublic void register() {Thread t1 = new Thread(new RegisterSingletonThread());Thread t2 = new Thread(new RegisterSingletonThread());t1.start();t2.start();try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("end");}/*** 注册式单例 序列化破坏单例*/@Testpublic void registerSerializable() {RegisterSingleton r1 = null;RegisterSingleton r2 = RegisterSingleton.getInstance();try {//序列化FileOutputStream fileOutputStream = new FileOutputStream("temp");ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);objectOutputStream.writeObject(r2);//反序列化FileInputStream fileInputStream = new FileInputStream("temp");ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);r1 = (RegisterSingleton) objectInputStream.readObject();//打印结果System.out.println(r1 == r2);} catch (Exception e) {e.printStackTrace();}}/*** 反射暴力获取单例*/@Testpublic void registerReflect() {try {Class<RegisterSingleton> registerSingletonClass = RegisterSingleton.class;Constructor<RegisterSingleton> declaredConstructor = registerSingletonClass.getDeclaredConstructor();declaredConstructor.setAccessible(true);RegisterSingleton innerSingleton = declaredConstructor.newInstance();System.out.println(innerSingleton);} catch (Exception e) {e.printStackTrace();}}/*** 容器式 注册单例*/@Testpublic void container() {Thread t1 = new Thread(new ContainerSingletonThread());Thread t2 = new Thread(new ContainerSingletonThread());t1.start();t2.start();try {Thread.sleep(5L);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("end");// Object bean = ContainerSingleton.getBean("com.xy.blog.test.model.Person");// System.out.println(bean);}}
**
