单例设计模式
常见的五种单例模式实现方式– 主要:
- 饿汉式(线程安全,调用效率高。 但是,不能延时加载。)
- 懒汉式(线程安全,调用效率不高。 但是,可以延时加载。)
-
其他:
- 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
- 静态内部类式(线程安全,调用效率高。 但是,可以延时加载)
- 枚举式(线程安全,调用效率高,不能延时加载。并且可以天然的防止反射和反序列化漏洞!)
-
如何选用?
-
单例对象 占用 资源 少,不需要 延时加载
- 枚举式 好于 饿汉式
-
单例对象 占用 资源 大,需要 延时加载:
- 静态内部类式 好于 懒
-
饿汉
public class OneObject {
private static final OneObject OBJECT = new OneObject();
private OneObject () {}
public static OneObject build () {
return OBJECT;
}
}
懒汉
public class OneObjectLaz {
private static OneObjectLaz laz;
private OneObjectLaz () {}
public static OneObjectLaz build () {
synchronized (OneObjectLaz.class) {
if (null == laz) laz = new OneObjectLaz();
}
return laz;
}
}
多线程测试
for (int i = 0; i < 10; i++) {
new Thread(() -> {
OneObjectLaz build = OneObjectLaz.build();
System.out.println(build.hashCode());
}).start();
}
通过反射机制暴力范围 private 构造器, 从而达到多实例
Constructor<OneObject> constructor = OneObject.class.getDeclaredConstructor();
constructor.setAccessible(true);
OneObject newInstance = constructor.newInstance();
System.out.println(newInstance);
解决方案
public class OneObjectLaz {
private static OneObjectLaz laz;
private OneObjectLaz () {
if (laz != null) throw new RuntimeException("对象必须保证单例!");
}
public static OneObjectLaz build () {
synchronized (OneObjectLaz.class) {
if (null == laz) laz = new OneObjectLaz();
}
return laz;
}
}
防止序列化破解单例
public class OneObjectLaz {
private static OneObjectLaz laz;
private OneObjectLaz () {
if (laz != null) throw new RuntimeException("对象必须保证单例!");
}
public static OneObjectLaz build () {
synchronized (OneObjectLaz.class) {
if (null == laz) laz = new OneObjectLaz();
}
return laz;
}
/**
* 防止单例, 反序列化破解
* 如果定义了: readResolve 方法在反序列时直接返回方法指定的对象, 不需要new了
*/
private Object readResolve() throws ObjectStreamException {
return laz;
}
}
要想真正的实现单利漏洞还是很多的所以
jdk
提供了新特性:enum
public enum One {
ONE, TWO, THREE;
}

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
责任链设计模式
责任链的应用场景 Servlet API 中的 Filter 过滤器 MVC 框架中的拦截器 . . . 简单使用责任链模式拆分 Servlet API 中的过滤器 模拟 Servlet 中的 Request 对象 /** * @desc <b>模拟 Servlet 中的 Request 对象</b> * * @author jiang ru yi */ public class HttpServletRequest { private String requestContext; private Map<String, Object> requestParam = new HashMap<>(); public String getRequestContext() { return requestContext; } public void setRequestContext(String requestContext) { this.requestContext = requestContext; } public void setR...
-
下一篇
30 岁转行做Python开发晚吗?而且是零基础
最近有小伙伴问小编,30 岁转行做Python开发晚吗? 小编想说,其实无论男女,只要想学,有这个动力,就直接去行动。无论年龄,无论性别,只要你想一直勇往直前,那么想做的就去做吧~这里有一句话与大家分享:种下一棵树最好的时间是十年以前,其次就是现在! Python学习路线一:Python基础 必学知识:【Linux基础】【Python基础语法】【Python字符串】【文件操作】【异常处理】【Python面向对象】【项目实战】 路线讲解:该路线循序渐进,科学合理,帮助学习者建立正确的编程思想,具备基本的编程能力; Python学习路线二:Python高级编程 必学知识:【Python平台迁移Linux】【Python常用第三方库】【Python高级语法】【Python正则表达式】【网路编程】【系统编程】【数据结构与算法】【项目实战】 路线讲解:该路线强调数据结构和算法的学习,着重提升学习者的编程核心能力;使学习者能够熟练掌握Python高级用法及网络相关知识,能够独立承担Python网络相关的开发; Python学习路线三:web前端开发 必学知识:【HTML】【CSS】【UI基础】【J...
相关文章
文章评论
共有0条评论来说两句吧...