看的视频:https://www.bilibili.com/video/av43896218/?p=286

实现方式:(构造器私有,提供一个外部可以访问的方法(可以提供实例)

1、饿汉式:线程安全,调用效率高, 不能延时加载

2、懒汉式:线程安全,调用效率不高,可以延时加载(要用的时候才加载  )

3、双重锁检测式:“由于JVM底层内部模型原因,偶尔会出现问题,不建议使用”

4、静态内部类式:线程安全,调用效率高,且可以实现延时加载

(上面的四种方式都可以通过反射和反序列化 破坏 单例模式)

5、枚举:线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化

如果单例对象占用资源少,不需要延时加载:

枚举式 优于 饿汉式

如果单例对象占用资源大, 需要延时加载:

静态内部类式 优于 懒汉式

饿汉式:

/*
饿汉式: 最开始就已经把实例给创建好了
*/
public class Singleton01 {
public static Singleton01 instance = new Singleton01(); //一开始就已经创建好了
private Singleton01(){
}
public static Singleton01 getInstance(){
return instance;
}
}

懒汉式:

/*
懒汉式: 用的时候才会初始化实例 效率不高就是因为有synchronized这个关键字
*/
public class Singleton02 {
private static Singleton02 instance = null;
private Singleton02(){
}
public static synchronized Singleton02 getInstance(){
if(instance == null){
instance = new Singleton02();
}
return instance;
}
}

静态内部类:

/*
静态内部类: 只有在主动调用这个类的时候才会加载 外部类加载的时候 静态内部类不会加载
*/
public class Singleton03 {
static class Inner{
private static Singleton03 instance = new Singleton03();
}
private Singleton03(){ }
public static Singleton03 getInstance(){
return Inner.instance;
}
}

枚举:

/*
枚举 天然的可以防止 反射和反序列化
*/
public enum Singleton04 {
INSTANCE; //就表示一个实例 获取的时候直接 Singleton04.INSTANCE
public void method(){
//这里可以写一些方法
}
}

通过反射破坏单例模式:

public class Test01 {
public static void main(String[] args) throws Exception{
Class<?> clazz = Class.forName("com.test.Singleton01");
//获取构造函数:
Constructor c = clazz.getDeclaredConstructor();
c.setAccessible(true); //对于私有属性和方法 设置为允许访问
//通过构造函数 构造实例
Singleton01 singleton001 = (Singleton01)c.newInstance();
Singleton01 singleton002 = (Singleton01)c.newInstance();
System.out.println(singleton001 == singleton002); // false
}
}

如何破坏反射:

public class Singleton01 {
private static boolean flag = false; //标志位
public static Singleton01 instance = new Singleton01(); //一开始就已经创建好了
// 上面的已经调用过一次 这个私有的构造函数了

private Singleton01(){ //反射的时候操作的就是这个私有的构造函数
synchronized (Singleton01.class){
if(flag == false){
flag = true;
}else{ //表示第二次用构造函数进行实例化
throw new RuntimeException("单例模式正在被破坏");
}
}
}
public Singleton01 getInstance(){
return instance;
}
}

在用反射就会报错....

通过反序列化破坏单例模式:

对象序列化:将对象状态转换为字节流的过程,可以将其保存到磁盘文件中或者通过网络发送到任何其他程序中。

反序列化:将字节流转化为对象的过程。

public class Test01 {
public static void main(String[] args) throws Exception{

//序列化 singleton001 Singleton01要实现 Serializable
Singleton01 singleton001 = Singleton01.getInstance();
Singleton01 singleton002 = Singleton01.getInstance();
FileOutputStream fos = new FileOutputStream("d:/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(singleton001);
oos.close();
fos.close(); //反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));
Singleton01 singleton003 = (Singleton01)ois.readObject(); System.out.println(singleton001 == singleton002); //true
System.out.println(singleton001 == singleton003); //false
}
}

防止反序列化:

public class Singleton01 implements Serializable {
public static Singleton01 instance = new Singleton01(); //一开始就已经创建好了
private Singleton01(){
}
public static Singleton01 getInstance(){
return instance;
}
//在反序列化的时候 直接调用这个方法 返回instance 而不是返回反序列化后的新对象
private Object readResolve() throws ObjectStreamException {
return instance;
}
}

最新文章

  1. ASP.NET MVC学习之母版页和自定义控件的使用
  2. Centos7搭建需要mysql的网站
  3. javascript多态 - 类形式实现demo
  4. shell 删除某个目录下的重复文件
  5. java.lang.NullPointerException 空指针异常
  6. uva 572 oil deposits——yhx
  7. 详解 Qt 线程间共享数据(用信号槽方式)
  8. Day07_面向对象第二天
  9. 设置VMWARE通过桥接方式使用主机无线网卡上网
  10. ACM 中常用的算法有哪些? 2014-08-21 21:15 40人阅读 评论(0) 收藏
  11. 基于CSS3制作的鼠标悬停动画菜单
  12. jquery ajax请求后台 的简单例子
  13. ArcGIS Runtime for Android开发教程V2.0(1)基本概念
  14. 安全测试常见的10个问题 ZT
  15. cloudstack安装篇1-linux命令修改IP信息
  16. 在JavaScript的数组中进行数组元素查找和替换(JS的indexOf等)
  17. Delphi中类的运行期TypeInfo信息结构说明
  18. Bootstrap实现轮播图
  19. ArrayList和CopyOnWriteArrayList
  20. if 语句

热门文章

  1. 如何做好FAE工作及FAE职位发展————资深FAE总结推荐
  2. Django使用Ace实现在线编辑器
  3. C语言编译器开发之旅(开篇)
  4. IOS 小组件(7):小组件点击交互
  5. 2021.5.23 noip模拟2(排序|划艇|放棋子)
  6. java中的NIO和IO到底是什么区别?20个问题告诉你答案
  7. docker磁盘空间清理办法
  8. selenium元素定位陷阱规避
  9. java基础第一节课随笔
  10. 『居善地』接口测试 — 13、Moco框架的使用