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)? 设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设 ...
随机推荐
- mariaDB vs mysql
mariaDB vs mysql 今天遇到一个库使用的是mariaDB的数据库版本 Server version: 10.1.20-MariaDB MariaDB Server 理了一下mariaDB ...
- Python进阶:设计模式之迭代器模式
在软件开发领域中,人们经常会用到这一个概念——“设计模式”(design pattern),它是一种针对软件设计的共性问题而提出的解决方案.在一本圣经级的书籍<设计模式:可复用面向对象软件的基础 ...
- 8天入门docker系列 —— 第三天 使用aspnetcore小案例熟悉对镜像的操控
上一篇我们聊到了容器,现在大家应该也知道了,没有镜像就没有容器,所以镜像对docker来说是非常重要的,关于镜像的特性和原理作为入门系列就不阐 述了,我还是通过aspnetcore的小sample去熟 ...
- C#设计模式整理
我居然连一月一随笔都没有,啊啊啊,忙死个人 这个随笔主要是记录基于自己学习[美]James W.Cooper著的<C# Design Patterns : A Tutorial>一书中常用 ...
- Oracle数据库知识要点
一.卸载安装(来自百度经验) 完全卸载: 1. 停止相关服务 2. 运行Universal Installer,卸载产品 3. 清理注册表 4. 重启电脑,删除目录(Oracle文件夹和app文件夹) ...
- Spring Boot 入门(六):集成 treetable 和 zTree 实现树形图
本篇文章是接着Spring Boot 入门(五):集成 AOP 进行日志管理写的,主要集成了树形图,在部门列表或者权限列表中,树形图经常被用上.主要是根据相应的 API 凭借 html 字符串 1.t ...
- pytest进阶之xunit fixture
前言 今天我们再说一下pytest框架和unittest框架相同的fixture的使用, 了解unittest的同学应该知道我们在初始化环境和销毁工作时,unittest使用的是setUp,tearD ...
- Nginx反向代理解决iframe跨域问题
前言 这几天有个需求:做个表单页面,要求后台人员能自定义发布表单,用户来填写表单.我一想,这不麦克表单有现成的吗,拿来就用!发布表单后,可以选择使用iframe方式嵌入网站,一切顺利. 当时的网站是h ...
- React 基础入门
React 起源于 Facebook 内部项目,是一个用来构建用户界面的 Javascript 库,相当于MVC架构中的V层框架,与市面上其他框架不同的是,React 把每一个组件当成了一个状态机,组 ...
- 【STM32H7教程】第3章 STM32H7整体把控
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第3章 STM32H7整体把控 初学STM32H7一 ...