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的设计模式 - 单例模式的更多相关文章

  1. 单例模式——Java EE设计模式解析与应用

    单例模式 目录: 一.何为单例 二.使用Java EE实现单例模式 三.使用场景 一.何为单例 确保一个类只有一个实例,并且提供了实例的一个全局访问点 1.1 单例模式类图               ...

  2. java设计模式单例模式 ----懒汉式与饿汉式的区别

    常用的五种单例模式实现方式 ——主要: 1.饿汉式(线程安全,调用率高,但是,不能延迟加载.) 2.懒汉式(线程安全,调用效率不高,可以延时加载.) ——其他: 1.双重检测锁式(由于JVM底层内部模 ...

  3. 最简单的设计模式——单例模式的演进和推荐写法(Java 版)

    前言 如下是之前总结的 C++ 版的:软件开发常用设计模式—单例模式总结(c++版),对比发现 Java 实现的单例模式和 C++ 的在线程安全上还是有些区别的. 概念不多说,没意思,我自己总结就是: ...

  4. Java设计模式の单例模式

    -------------------------------------------------- 目录 1.定义 2.常见的集中单例实现 a.饿汉式,线程安全 但效率比较低 b.单例模式的实现:饱 ...

  5. JAVA设计模式-单例模式(Singleton)线程安全与效率

    一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...

  6. Java设计模式 - - 单例模式 装饰者模式

    Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...

  7. Java与设计模式之单例模式(下) 安全的单例模式

          关于单例设计模式,<Java与设计模式之单例模式(上)六种实现方式>介绍了6种不同的单例模式,线程安全,本文介绍该如何保证单例模式最核心的作用——“实现该模式的类有且只有一个实 ...

  8. Java与设计模式之单例模式(上)六种实现方式

           阎宏博士在<JAVA与模式>中是这样描述单例模式的:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类.      ...

  9. Java基础知识之设计模式--单例模式

    Java设计模式--单例模式 声明:本文根据慕课网汤小洋老师的精品课程整理来的:慕课网 什么是设计模式(Design Pattern)? 设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设 ...

随机推荐

  1. asp.net core 3.0 gRPC框架小试

    什么是gRPC gRPC是google开源的一个高性能.跨语言的RPC框架,基于HTTP2协议,采用ProtoBuf 定义的IDL. gRPC 的主要优点是: 现代高性能轻量级 RPC 框架. 协定优 ...

  2. 从壹开始前后端 [vue后台] 之一 || 权限后台系统 1.0 正式上线

    缘起 哈喽各位小伙伴周三好,春节已经过去好多天了,群里小伙伴也各种催搞了,新年也接了新项目,比较忙,不过还是终于赶上这个二月的尾巴写了这篇文章,也把 vue 权限后台上线了(项目地址:http://1 ...

  3. SQLI LABS Challenges Part(54-65) WriteUp

    终于到了最后一部分,这些关跟之前不同的是这里是限制次数的. less-54: 这题比较好玩,10次之内爆出数据.先试试是什么类型: ?id=1' and '1 ==>>正常 ?id=1' ...

  4. Python-爬取校花网视频(单线程和多线程版本)

    一.参考文章 python爬虫爬取校花网视频,单线程爬取 爬虫----爬取校花网视频,包含多线程版本 上述两篇文章都是对校花网视频的爬取,由于时间相隔很久了,校花网上的一些视频已经不存在了,因此上述文 ...

  5. 实验二 request、out对象使用

    request.out对象使用 一.实验目的 1.掌握代码片段中的注释的应用: 2.掌握JSP脚本标示---Java代码片段的应用. 二.实验内容 1.设计教师与学生不同登陆界面,如下图: 2.验证码 ...

  6. 教你如何一键反编译获取任何微信小程序源代码(图形化界面,傻瓜式操作)

    一键获取微信小程序源代码 Tips: 一键获取微信小程序源码, 使用了C#加nodejs制作 直接解压在D盘根目录下后就可以使用 将小程序文件放到 wxapkg目录下3 这个目录下有一些demo 可以 ...

  7. 产品经理之PRD详解

    文章大纲 一.PRD基础二.PRD要素讲解三.相关模板下载四.参考文章   一.PRD基础 1. PRD简介    PRD中文意思为:产品需求文档.PRD的主要使用对象有:开发.测试.项目经理.交互设 ...

  8. 批量插入一张表的数据,并且生成不同的uuid 字符截取 批量更新 去除重复数据

    INSERT INTO party_branchSELECT UUID(),m.name,m.secreta_name,m.contacts_name,m.contact_phon,m.categor ...

  9. iOS屏幕适配 支持新手机 iPhone XR iPhone XS 超简单

    随着苹果爸爸发布了 超牛叉的iPhone iPhone X .iPhone XR.iPhone XS .iPhone XS Max.开发者的适配工作要开始了. 停,

  10. Vault安装、配置、使用

    一.环境搭建 官网指导步骤:https://learn.hashicorp.com/vault/#getting-started 1. 下载vault安装文件 2. dev环境启动 ./vault s ...