单例模式全解析:5种写法 + 破坏与防护
文章目录什么是单例模式?实现方式饿汉式懒汉式方式一线程不安全方式二同步方法方式三双重检查锁 DCL枚举什么是单例模式?保证一个类在全局只有一个实例并提供一个全局访问点。适用场景配置类、连接池、日志对象等全局唯一的资源。实现方式饿汉式类加载时就创建实例天然线程安全。classHungrySingleton{privatestaticfinalHungrySingletoninstancenewHungrySingleton();privateHungrySingleton(){}publicstaticHungrySingletongetInstance(){returninstance;}}优点简单线程安全缺点不管用不用都会创建对象可能浪费内存懒汉式方式一线程不安全classLazySingleton{privatestaticLazySingletoninstance;privateLazySingleton(){}publicstaticLazySingletongetInstance(){if(instancenull){instancenewLazySingleton();}returninstance;}}延迟创建对象但多线程下可能创建多个实例线程不安全。方式二同步方法classSafeThreadLazySingleton{privatestaticSafeThreadLazySingletoninstance;privateSafeThreadLazySingleton(){}publicstaticsynchronizedSafeThreadLazySingletongetInstance(){if(instancenull){instancenewSafeThreadLazySingleton();}returninstance;}}加锁保证线程安全但每次获取对象都要经过锁竞争性能不好。方式三双重检查锁 DCLclassDCLLazySingleton{privatestaticvolatileDCLLazySingletoninstance;privateDCLLazySingleton(){}publicstaticDCLLazySingletongetInstance(){if(instancenull){synchronized(DCLLazySingleton.class){if(instancenull){instancenewDCLLazySingleton();}}}returninstance;}}第一个 if判断对象是否已经创建避免每次都进入同步块提升性能。第二个 if高并发下第一个 if 可能同时放进来多个线程如 A、B、C它们被锁阻塞。A进入临界区创建了对象后退出B 或 C 再进来时第二个 if 告诉它对象已存在直接返回。volatile 的作用防止指令重排序。new 一个对象分三步① 分配内存 → ② 初始化对象 → ③将引用指向内存地址。JVM 可能将顺序优化为①③②此时另一个线程拿到的是未初始化完成的对象产生空指针问题。volatile禁止这种重排序保证对象完整创建后才对外可见。枚举enumEnumSingleton{INSTANCE;publicvoiddoSomething(){// 业务方法}}// 使用EnumSingleton.INSTANCE.doSomething();简洁优雅属于饿汉式。是唯一不会被反射和反序列化破坏的单例实现Josh Bloch 在《Effective Java》中推荐的方式。除枚举外其他单例都可以通过以下方式强行创建新实例反射Constructor.setAccessible(true) 绕过私有构造器反序列化对象实现 Serializable 后反序列化会创建新对象枚举在 JVM 层面做了保护这两种方式对它均无效。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2477721.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!