wordpress本地网站搭建整套课程,网站建设和网页建设的区别,汉中专业网站建设价格,网站的建设可以起到什么作用是什么目录 简介
饿汉式
懒汉式
双重检测锁式
静态内部类式
枚举单例
测试
测试单例模式#xff1a;
测试五种单例模式在多线程环境下的效率
问题#xff08;拓展#xff09;
例#xff1a;反射破解单例模式
例#xff1a;反序列化破解单例模式
总结#xff1a;如何…目录 简介
饿汉式
懒汉式
双重检测锁式
静态内部类式
枚举单例
测试
测试单例模式
测试五种单例模式在多线程环境下的效率
问题拓展
例反射破解单例模式
例反序列化破解单例模式
总结如何用 简介
单例对象Singleton是一种常用的设计模式。在Java应用中单例对象能保证在一个 JVM 中该对象只有一个实例存在。这样的模式有几个好处
单例模式的优点
由于单例模式只生产一个实例减少了系统性能开销当一个对象的产生需要比较多的资源时如读取配置、产生其他依赖对象时则可以通过在应用启动时直接产生一个单例对象然后永久驻留内存的方式来解决单例模式可以在系统设置全局的访问点优化环境共享资源访问例如可以设计一个单例类负责所以数据表的映射处理
常见的五种单例模式实现方式
主要 饿汉式线程安全调用效率高但是不能延迟加载懒汉式线程安全调用效率不高但是可以延迟加载其他 双重检测锁式由于 JVM 底层内部模型原因偶尔会出问题不建议使用静态内部类式线程安全调用效率高但是可以延时加载枚举单例线程安全调用效率高不能延时加载
饿汉式
/*** ProjectName:* Package: com.example.gof23.creational_patterns.singleton* ClassName: SingletonHg* Description: 饿汉式单例模式Hungry* Author: qfxl* CreateDate: 2024/09/09 23:00* Version: 1.0.0*/
public class SingletonHungry {//类初始化时立即加载这个对象//在类加载器加载时是天然的线程安全模式同时因为是立即加载所以没有延迟加载的优势private static SingletonHungry instance new SingletonHungry();//私有化构造器private SingletonHungry() {}//方法没有同步调用效率高public static SingletonHungry getInstance() {return instance;}
}
懒汉式
/*** ProjectName:* Package: com.example.gof23.creational_patterns.singleton* ClassName: SingletonLazy* Description: 懒汉式单例模式Lazy* Author: qfxl* CreateDate: 2024/09/09 23:00* Version: 1.0.0*/
public class SingletonLazy {//类初始化时不初始化这个对象实现懒加载 或者叫 延迟加载lazy load真正用到的时候才加载private static SingletonLazy instance;//私有化构造器private SingletonLazy() {}//方法同步调用效率低public static synchronized SingletonLazy getInstance() {if (instance null) {instance new SingletonLazy();}return instance;}
}
双重检测锁式
/*** ProjectName:* Package: com.example.gof23.creational_patterns.singleton* ClassName: SingletonDC* Description: 双重检测锁式单例模式Double Checked Locking* Author: qfxl* CreateDate: 2024/09/09 23:10* Version: 1.0.0*/
public class SingletonDC {//使用了volatile关键字后重排序被禁止所有的写write操作都将发生在读read操作之前private volatile static SingletonDC instance;//私有化构造器private SingletonDC() {}//双重检测锁式public SingletonDC getInstance() {if (instance null) {synchronized (SingletonDC.class) {if (instance null) {instance new SingletonDC();}}}return instance;}
}
静态内部类式
/*** ProjectName:* Package: com.example.gof23.creational_patterns.singleton* ClassName: SingletonSIC* Description: 静态内部类式单例模式Static Inner Class* Author: qfxl* CreateDate: 2024/09/09 23:10* Version: 1.0.0*/
public class SingletonSIC {private static class SingletonClassInstance {private static final SingletonSIC instance new SingletonSIC();}//私有化构造器private SingletonSIC() {}public static SingletonSIC getInstance(){return SingletonClassInstance.instance;}
}
枚举单例
/*** ProjectName:* Package: com.example.gof23.creational_patterns.singleton* ClassName: SingletonEnum* Description: 枚举类单例模式Enum* Author: qfxl* CreateDate: 2024/09/09 23:10* Version: 1.0.0*/
public enum SingletonEnum {//这个枚举元素本身就是单例对象没有延时加载INSTANCE;//添加自己需要的操作public void singletonOperation() {}
}
测试
测试单例模式
public class Client {public static void main(String[] args) {//测试饿汉式单例模式HungrySingletonHungry hungry1 SingletonHungry.getInstance();SingletonHungry hungry2 SingletonHungry.getInstance();System.out.println(hungry1);System.out.println(hungry2);//测试懒汉式单例模式SingletonLazy lazy1 SingletonLazy.getInstance();SingletonLazy lazy2 SingletonLazy.getInstance();System.out.println(lazy1);System.out.println(lazy2);//测试双重检测锁单例模式SingletonDC dc1 SingletonDC.getInstance();SingletonDC dc2 SingletonDC.getInstance();System.out.println(dc1);System.out.println(dc2);//测试静态内部类式单例模式SingletonSIC sic1 SingletonSIC.getInstance();SingletonSIC sic2 SingletonSIC.getInstance();System.out.println(sic1);System.out.println(sic2);//测试枚举单例模式SingletonEnum anEnum1 SingletonEnum.INSTANCE;SingletonEnum anEnum2 SingletonEnum.INSTANCE;System.out.println(anEnum1anEnum2);}
}
结果为
饿汉式com.example.gof23.creational_patterns.singleton.SingletonHungry1540e19d
饿汉式com.example.gof23.creational_patterns.singleton.SingletonHungry1540e19d
懒汉式com.example.gof23.creational_patterns.singleton.SingletonLazy677327b6
懒汉式com.example.gof23.creational_patterns.singleton.SingletonLazy677327b6
双重检测锁com.example.gof23.creational_patterns.singleton.SingletonDC14ae5a5
双重检测锁com.example.gof23.creational_patterns.singleton.SingletonDC14ae5a5
静态内部类com.example.gof23.creational_patterns.singleton.SingletonSIC7f31245a
静态内部类com.example.gof23.creational_patterns.singleton.SingletonSIC7f31245a
枚举单例true
测试五种单例模式在多线程环境下的效率
关注相对值即可不同的环境下测试值完全不一样
五种单例模式时间饿汉式SingletonHungry26ms懒汉式SingletonLazy186ms双重检测锁式SingletonDC40ms静态内部类式SingletonSIC31ms枚举单例SingletonEnum37ms
CountDownLatch 同步辅助类在完全一组正在其他线程中执行的操作之前它允许一个或多个线程一直等待countDown()当前线程调用此方法则计数减一建议放在 finally 里执行await()调用此方法会一直阻塞当前线程直到计时器的值为0
public class ClientTimes {public static void main(String[] args) throws InterruptedException {long start System.currentTimeMillis();int threadNum 10;final CountDownLatch countDownLatch new CountDownLatch(threadNum);for (int i 0; i threadNum; i) {new Thread(new Runnable() {public void run() {for (int i 0; i 1000000; i) {//分别对下面的单例模式进行测试SingletonHungry hungry SingletonHungry.getInstance();
// SingletonLazy lazy SingletonLazy.getInstance();
// SingletonDC dc SingletonDC.getInstance();
// SingletonSIC sic SingletonSIC.getInstance();
// SingletonEnum anEnum SingletonEnum.INSTANCE;}countDownLatch.countDown();}}).start();}//main线程阻塞直到计数器变为0才会继续执行countDownLatch.await();long end System.currentTimeMillis();System.out.println(总耗时 (end - start));}
} 测试结果如上表格
问题拓展
反射可以破解上面几种不包含枚举式实现反式可以在构造方法中手动抛出异常控制反序列化可以破解上面几种不包含枚举式实现方式可以通过定义 readResolver() 防止获得不同的对象 反序列化时如果对象所在的类定义了 readResolver()实际是一种回调定义返回那个对象
例反射破解单例模式
package com.example.gof23.creational_patterns.singleton.expand;public class SingletonDemo {private static SingletonDemo instance new SingletonDemo();//私有化构造器private SingletonDemo() {}public static SingletonDemo getInstance() {return instance;}} public class Test_reflect {public static void main(String[] args) throws Exception {//通过反射来破解单例模式通过反射的方式直接调用私有化构造器ClassSingletonDemo clazz (ClassSingletonDemo) Class.forName(com.example.gof23.creational_patterns.singleton.expand.SingletonDemo);ConstructorSingletonDemo c clazz.getDeclaredConstructor(null);c.setAccessible(true);//跳过权限的检测使其可以访问私有的方法SingletonDemo sd1 c.newInstance();SingletonDemo sd2 c.newInstance();System.out.println(sd1);System.out.println(sd2);}
} 结果为
com.example.gof23.creational_patterns.singleton.expand.SingletonDemo1540e19d
com.example.gof23.creational_patterns.singleton.expand.SingletonDemo677327b6 防止反射破解单例模式在构造方法中手动抛出异常控制
package com.example.gof23.creational_patterns.singleton.expand;public class SingletonDemo {private static SingletonDemo instance new SingletonDemo();//私有化构造器private SingletonDemo() {//防止反射获取私有化的构造方法从而破解单例模式if (instance ! null) {throw new RuntimeException();}}public static SingletonDemo getInstance() {return instance;}} 再运行的结果为
com.example.gof23.creational_patterns.singleton.expand.SingletonDemo135fbaa4
com.example.gof23.creational_patterns.singleton.expand.SingletonDemo135fbaa4 例反序列化破解单例模式
package com.example.gof23.creational_patterns.singleton.expand;import java.io.Serializable;public class SingletonDemo implements Serializable {private static SingletonDemo instance new SingletonDemo();//私有化构造器private SingletonDemo() {}public static SingletonDemo getInstance() {return instance;}} public class Test_serializable {public static void main(String[] args) throws Exception {//通过反序列化的方式构造多个对象SingletonDemo instance1 SingletonDemo.getInstance();FileOutputStream fos new FileOutputStream(e:/a.txt);ObjectOutputStream oos new ObjectOutputStream(fos);oos.writeObject(instance1);FileInputStream fis new FileInputStream(e:/a.txt);ObjectInputStream ois new ObjectInputStream(fis);SingletonDemo instance2 (SingletonDemo) ois.readObject();System.out.println(instance1);System.out.println(instance2);}
} 结果为
com.example.gof23.creational_patterns.singleton.expand.SingletonDemo135fbaa4
com.example.gof23.creational_patterns.singleton.expand.SingletonDemo58372a00
防止反序列化破解单例模式通过定义 readResolver() 防止获得不同的对象
package com.example.gof23.creational_patterns.singleton.expand;import java.io.Serializable;public class SingletonDemo implements Serializable {private static SingletonDemo instance new SingletonDemo();//私有化构造器private SingletonDemo() {//防止反射获取私有化的构造方法从而破解单例模式if (instance ! null) {throw new RuntimeException();}}public static SingletonDemo getInstance() {return instance;}//在反序列化时如果定义了此方法则直接返回此方法中的对象无需单独再创建新对象private Object readResolve() {return instance;}} 再运行结果为
com.example.gof23.creational_patterns.singleton.expand.SingletonDemo135fbaa4
com.example.gof23.creational_patterns.singleton.expand.SingletonDemo135fbaa4
总结如何用
单例对象占用资源少不需要延迟加载 枚举式 好于 饿汉式单例对象占用资源大需要延迟加载 静态内部类式 好于 懒汉式