java的设计模式 - 单例模式
java 面试中单例模式基本都是必考的,下面记录一下
饿汉式
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
其实真心觉得没什么问题
private Singleton来修饰可以防止创建多个实例- 没有延迟加载?这是需求不同好吗!有很多的需求是希望一开始就加载好的,不希望要用的时候再加载的,比如是
java.lang.Runtime
但面试的时候,你不能这样回答,面试官不开心的,你要回答
- 没有延迟加载
- 譬如 Singleton 实例的创建是依赖参数或者配置文件的,在 getInstance() 之前必须调用某个方法设置参数给它,是不能使用。(在构造函数上传参不行吗?,不考虑延迟加载)
懒汉模式
public class Singleton {
private volatile static Singleton instance; //声明成 volatile
private Singleton (){}
public static Singleton getSingleton() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
你看加个延迟加载
- 要将 instance 声明个 volatile 好让在多线程的环境下可见
- 又要注意在多线程的情况下要主要加锁,因为会出现一个线程认为是空要构造对象,而另一个对象也认为是空要构造对象是情况
麻烦!!!
但也有应用场景的,在资源占用很多,又不常用的情况下,可以考虑用懒汉模式
懒汉式二式 —— 内部静态类
public class Singleton {
private final static class SingleHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return SingleHolder.INSTANCE;
}
}
因为这个是 JVM 保证其线性安全性的,而且会在加载的时候创建,又不依赖版本,所以以前会比较推荐。
致命的危险
其实上面的东东都有致命的危险!反射
上面按正常人类的做法是不会产生多个实例,如果会产生多个实例是说明上面的方式或多或少不够完美 ,比如反射
@Test
public void test() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Constructor<?> cls = Singleton.class.getDeclaredConstructor();
cls.setAccessible(true);
Singleton singleton = (Singleton) cls.newInstance();
assertNotEquals(singleton,Singleton.getInstance());//明显这两个对象是不一样的!!!
}
也就是说上面的方式面对复杂的序列化或者反射攻击,可能会出现问题!(当然要先实现 Serializable 接口)
比如:
@Test
public void test() throws ClassNotFoundException, IOException {
//序列化对象到文件
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("singleton"));
objectOutputStream.writeObject(Singleton.getInstance());
//从文件中读取对象
File file = new File("singleton");
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
Singleton singleton = (Singleton) objectInputStream.readObject();
//判断是否是同一个对象
assertNotEquals(singleton,Singleton.getInstance());
}
当然也有应对序列化的方式。
就是在类中添加readResolve函数,因为反序列化中,如果存在这个函数,序列化的结果就是这函数的值。
所以你在要序列化中的类添加这句就可以了。
private Object readResolve() {
return getInstance();
}
但面对反射就确实无力了。
最好的方式 - 枚举类
public enum SingletonEnum {
INSTANCE;
}
- 面对反射:jvm 直接禁止了通过反射构造枚举实例的行为!
- 面对序列化:jvm 对 enum 类的序列化,不是调用 writeObject、readObject 这些方法的。结果是就算是序列化后再反序列化,结果都是一样。
以上
java的设计模式 - 单例模式的更多相关文章
- 单例模式——Java EE设计模式解析与应用
单例模式 目录: 一.何为单例 二.使用Java EE实现单例模式 三.使用场景 一.何为单例 确保一个类只有一个实例,并且提供了实例的一个全局访问点 1.1 单例模式类图 ...
- java设计模式单例模式 ----懒汉式与饿汉式的区别
常用的五种单例模式实现方式 ——主要: 1.饿汉式(线程安全,调用率高,但是,不能延迟加载.) 2.懒汉式(线程安全,调用效率不高,可以延时加载.) ——其他: 1.双重检测锁式(由于JVM底层内部模 ...
- 最简单的设计模式——单例模式的演进和推荐写法(Java 版)
前言 如下是之前总结的 C++ 版的:软件开发常用设计模式—单例模式总结(c++版),对比发现 Java 实现的单例模式和 C++ 的在线程安全上还是有些区别的. 概念不多说,没意思,我自己总结就是: ...
- Java设计模式の单例模式
-------------------------------------------------- 目录 1.定义 2.常见的集中单例实现 a.饿汉式,线程安全 但效率比较低 b.单例模式的实现:饱 ...
- JAVA设计模式-单例模式(Singleton)线程安全与效率
一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...
- Java设计模式 - - 单例模式 装饰者模式
Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...
- Java与设计模式之单例模式(下) 安全的单例模式
关于单例设计模式,<Java与设计模式之单例模式(上)六种实现方式>介绍了6种不同的单例模式,线程安全,本文介绍该如何保证单例模式最核心的作用——“实现该模式的类有且只有一个实 ...
- Java与设计模式之单例模式(上)六种实现方式
阎宏博士在<JAVA与模式>中是这样描述单例模式的:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. ...
- Java基础知识之设计模式--单例模式
Java设计模式--单例模式 声明:本文根据慕课网汤小洋老师的精品课程整理来的:慕课网 什么是设计模式(Design Pattern)? 设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设 ...
随机推荐
- 图解Java线程的生命周期,看完再也不怕面试官问了
文章首发自个人微信公众号: 小哈学Java https://www.exception.site/java-concurrency/java-concurrency-thread-life-cycle ...
- 『Möbius函数与Möbius反演』
Möbius函数 定义 设正整数\(n\)算数基本定理分解后为\(n=\prod_{i=1}^{k}p_i^{a_i}\),定义函数 \[ \mu(n)= \begin{cases} 0\ \ (\e ...
- Python爬虫入门教程 53-100 Python3爬虫获取三亚天气做旅游参照
爬取背景 这套课程虽然叫爬虫入门类课程,但是里面涉及到的点是非常多,十分检验你的基础掌握的牢固程度,代码中的很多地方都是可以细细品味的. 为什么要写这么一个小东东呢,因为我生活在大河北,那雾霾醇厚的很 ...
- java并发编程(1) --并发基础及其锁的原理
引言 多线程的知识点是一个庞大的体现,对此也是一知半解.一直想系统的深入的学习多线程的知识,奈何一直没有找到机会,好吧,其实就是懒.最近在项目中接触到一个多并发的项目,在项目中踩了无数的坑.在此下定决 ...
- 什么是TensorBoard?
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面: 从零开始学TensorFlow[01-搭 ...
- transition-timing-function 属性
以相同的速度从开始到结束的过渡效果: div { transition-timing-function: linear; -moz-transition-timing-function: linear ...
- 小程序 wepy框架 + iview-weapp的用法
最近在弄wepy的时候在想有没有什么ui比较合适一点的wepy的,也是在网上看了好久发现iview还不错.引用简单,上手超快,组件绚丽!当然,这里还介绍下微信官方建议的框架也是和不错的,有需要的可以看 ...
- 学习 day4 html 盒子模型
盒子模型 1.框模型 框:页面上所有元素都可以称为“框” 框模型:(BOX Model),又称盒子模型 定义框处理元素内容.内边距padding.外边距margin.边框的样式border 外边距ma ...
- Echarts 南海诸岛简图显示位置调整
最近需要echart同时显示海南岛和南海诸岛,开始想寻找南海诸岛的数据,经过查找,这种简图数据是没有的(china.js地图数据一一找过了),下图是echarts的一些示例,没有满足我们的要求 ...
- T-SQL语法基础
一.T-SQL语言的分类 DDL-数据定义语言 create-创建 alter-修改 drop-删除(针对对象) DML-数据操作语言 Insert-插入 update-更新 delete-删除(针对 ...