目录

第一种:非延迟加载

第二种:同步延迟加载

第三种:双重检测同步延迟加载

第四种:使用内部类实现延迟加载(推荐)

第五种:枚举


单例模式:确保在任何时候,该类只有唯一 一个实例。

单例的创建有两种方式:
1、非延迟加载:不管什么时候要使用,先提前创建实例。
2、延迟加载:等到真正要使用的时候才去创建实例,不用时不要去创建。

第一种:非延迟加载


public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}

第二种:同步延迟加载


public class Singleton {private static Singleton instance = null;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

多线程情况下,每一次获取,都需要获取同步锁,导致执行效率低下。

第三种:双重检测同步延迟加载


public class Singleton {private volatile static Singleton instance = null;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {    // 1if (instance == null) {         // 2instance = new Singleton(); // 3    (旧版本:还没初始化完成,就已经对其它线程可见了)}}}return instance;}
}

只需在第一次创建实例时才同步,一旦创建成功,以后获取实例时就不需要获取同步锁了。

注意:JDK5.0以后版本中 instance 为 volatile,双重检测同步延迟加载才有效。
旧版本Java中, 双重检测同步延迟加载失败的主要原因是:Java内存模型中指令序列的“乱序执行”。
假设代码执行以下指令序列:
  1. 线程 1 进入 getInstance() 方法。
  2. 由于 instance 为 null,线程 1 在 //1 处进入 synchronized 块。
  3. 线程 1 前进到 //3 处,但在构造函数执行之前,使 instance 成为非 null。
  4. 线程 1 被线程 2 预占。
  5. 线程 2 检查 instance 是否为 null。因为 instance 不为 null,线程 2 将 instance 引用返回一个构造完整但部分初始化了的 Singleton 对象。
  6. 线程 2 被线程 1 预占。
  7. 线程 1 通过运行 Singleton 对象的构造函数并将引用返回给它,来完成对该对象的初始化。
为展示此情况的发生情况,假设代码行 instance =new Singleton(); 执行了下列伪代码:
mem = allocate();      //为单例对象分配内存空间instance = mem;        //instance 引用指向内存,此时 instance 不为 null,但还未初始化construct(instance);   //调用构造函数进行初始化

可以看出旧版本中, instance =new Singleton() 不具有操作的原子性。

可能原因如下(待验证):

Java 1.5 以前对实例变量是直接在主存中读写的,也就是以上 3 行伪代码的每一步操作,对于其它线程都是可见的。

Java 1.5 以后,JMM发生了根本性的改变,以上 3 行伪代码都在线程的工作空间中完成的,在没有向主存写入变量之前,其它线程对这个过程都是不可见的。volatile 关键字在这里有两个作用,一是禁止指令序列的“乱序执行”,让重排后的指令之间的依赖变得有序,必须让变量初始化完成后,才能够执行依赖于它的其它指令;二是执行完 3 行伪代码后,立即把变量 instance 写入到主存,该变量才对其它线程可见。

第四种:使用内部类实现延迟加载(推荐)


public class Singleton {private Singleton() {//实例的初始化}static class SingletonHolder {static Singleton instance = new Singleton();}public static Singleton getInstance() {return SingletonHolder.instance;}
}

静态内部类SingletonHolder只会被初始化一次,因为在被类加载器加载后,对SingletonHolder的Class对象只会进行一次初始化。

第五种:枚举


public enum Singleton {  INSTANCE;  public void fun() {  }
}

 

单例模式-Java实现-非延迟加载、延迟加载相关推荐

  1. Java异步非阻塞编程的几种方式

    简介: Java异步非阻塞编程的几种方式 一. 从一个同步的Http调用说起 一个很简单的业务逻辑,其他后端服务提供了一个接口,我们需要通过接口调用,获取到响应的数据. 逆地理接口:通过经纬度获取这个 ...

  2. 单例模式——java设计模式

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

  3. java非负整数怎么设_使用JAVA将非负十进制整数n转换成b进制,递归方法与非递归方法...

    使用JAVA将非负十进制整数n转换成b进制,递归方法与非递归方法 使用JAVA将非负十进制整数n转换成b进制,递归方法与非递归方法 一.题目要求 将非负十进制整数n转换成b进制.(其中b=2~16) ...

  4. 用Java实现非阻塞通信

    用ServerSocket和Socket来编写服务器程序和客户程序,是Java网络编程的最基本的方式.这些服务器程序或客户程序在运行过程中常常会阻塞.例如当一个线程执行ServerSocket的acc ...

  5. 拉马努金的整数拆分全排列JAVA实现非递归

    拉马努金的整数拆分全排列JAVA实现非递归 点这里: 递归方式 结果是:组合成100的可能性共有:190569292种!! 不做详细说明了,需要看文字描述的,点上面链接跳转递归方式,查看详细说明 来, ...

  6. Java运行非Web的Springboot项目(测试类或启动主类两种方法)

    Java运行非Web的Springboot项目(测试类或启动主类两种方法) 前言 一.创建打开一个Springboot项目 二.运行项目 1.Test测试类运行 2.启动主类运行 三.持续运行不停止( ...

  7. java i 非原子性_java i++ 非原子操作

    java i++ 非原子操作 i++ 不是原子操作, 也就是说, 它不是单独一条指令, 而是 3 条指令: 1, 从内存中把 i 的值取出来放到 CPU 的寄存器中 2,CPU 寄存器的值 + 1 3 ...

  8. java day56【 Mybatis 延迟加载策略 、 Mybatis 缓存、Mybatis 注解开发 】

    第1章 Mybatis 延迟加载策略 1.1 何为延迟加载? 1.2 实现需求 1.3 使用 assocation 实现延迟加载 1.3.1 账户的持久层 DAO 接口 1.3.2 账户的持久层映射文 ...

  9. java 四种实现延迟加载的方法

    1. 延迟初始化 2. 虚拟代理(virtual proxy) 原文地址:   http://www.oodesign.com/proxy-pattern.html Intent The intent ...

最新文章

  1. 基于局部表面特征在杂乱场景中的三维物体识别
  2. python中四种进制的输出_Python基础语法和进制
  3. 用WebCollector爬取新浪微博数据
  4. 乐鑫代理-启明云端分享ESP32系列教程之二:Linux搭建esp-idf环境
  5. python操作redis中的list
  6. 使用Azure DevOps Pipeline实现.Net Core程序的CD
  7. 网络 传输层 | UDP协议与TCP协议详解(三次握手及四次挥手、滑动窗口、拥塞控制)
  8. join为什么每个字符都分割了 js_为什么 webpack4 默认支持 ES6 语法的压缩?
  9. ADS2022学习笔记(二)
  10. Class和class? 类对象和类的对象? 一篇文章让你摸到头脑
  11. Android Base64编码解码
  12. qcloud_cos 的安装问题
  13. python随机森林变量重要性_python机器学习之随机森林(七)
  14. 计算机专业大学排名(全168所学校)
  15. Excel提取18位/15位身份证出生日期②
  16. 腾讯技术团队整理,年度好文轻松彻底入门 Flutter,秒变大前端
  17. python行业中性_用python进行金融市场文本数据的情感计算
  18. 轻松学习JavaScript十一:JavaScript基本类型(包含类型转换)和引用类型
  19. 计算机对会计有什么好处,会计专业转行干过设计工作,这些宝贵经验和感悟,对你有用(三)...
  20. VintaSoft Twain.NET SDK,实现扫描文档

热门文章

  1. 嵌入式linux加载引导内核和根文件系统的方法
  2. JavaSE基础笔记
  3. QT次线程连接数据库
  4. Silverlight 4.0 Accordion 解决ScrollViewer 的问题
  5. Computer Systems A Programmer's Perspective(深入理解计算机系统)第一章读书笔记
  6. 实验吧web-易-what a fuck!这是什么鬼东西?
  7. Ubuntu14.04server 安装 fping
  8. 表单单选多选项清除默认样式小技巧
  9. 限制EditText只能输入小数点后两位
  10. 获取aplicationContext对象,从而获取任何注入的对象