单例模式五种实现方式以及在JDK中的体现

一、五种实现方式

1、饿汉式

  • 构造私有
  • 提供一个静态私有的成员常量,类型就是单例类型,值是用私有构造创造出来的唯一实例
  • 提供公共的静态方法获取上述的静态成员常量
public class Singleton1 implements Serializable {
//(1)构造私有
private Singleton1(){
//添加if判断防止单例模式被破坏
if(INSTANCE != null) {
throw new RuntimeException("单例构造器禁止反射调用");
}
System.out.println("private Singleton1()");
}
//(2)提供一个静态私有的成员常量,类型就是单例类型,值是用私有构造创造出来的唯一实例
private static final Singleton1 INSTANCE = new Singleton1();
//(3)提供公共的静态方法获取上述的静态成员常量
public static Singleton1 getInstance() {
return INSTANCE;
}
}

注意:对应所有的单例模式实现方式,如果实现Serializable接口,可能会被反射,反序列化等操作破坏单例,

2、枚举饿汉式

  • 枚举类,只定义一个变量
  • 构造私有
  • 提供公共的静态方法获取枚举常量
public enum Singleton2 {
//(1)枚举类,只定义一个变量
INSTANCE;
//(2)构造私有
private Singleton2(){
System.out.println("private Singleton3()");
}
//(3)获取枚举常量
private static Singleton2 getInstance(){
return INSTANCE;
} }

3、懒汉式

  • 构造私有
  • 提供一个静态私有的成员常量,类型就是单例类型,值为空
  • 当调用该方法时才new
  • 提供公共的静态方法获取上述的静态成员常量
public class Singleton3 {
//(2)声明静态变量为空
private static Singleton3 INSTANCE = null;
//(1)构造私有
private Singleton3(){
System.out.println("private Singleton1()");
}
//(3)提供公共的静态方法获取上述的静态成员变量
//添加synchronized保证在多线程情况下运行正常
public static synchronized Singleton3 getInstance() {
//(4)调用该方法时再new,通过判断是否为空可控制只创建一个实例
if(INSTANCE == null) {
INSTANCE=new Singleton3();
}
return INSTANCE;
}
}

注意:如果在多线程下,要防止多次创建实例,则在静态方法上添加synchronized,但其实我们只要在第一次调用时保证线程安全就可以,因此此方式的效率比较低,如果要提高效率,可以参考下述两种实现方式。

4、DCL懒汉式-双检索懒汉式

DCL懒汉式是为了保证多线程下运行正常,同时提高效率,也就是在静态方法中加锁之前判断是否已经创建了实例。同时静态变量使用volatile修饰

public class Singleton4 {
//(2)声明静态变量为空
private static volatile Singleton4 INSTANCE = null;//可见性,有序性
//(1)构造私有
private Singleton4(){
System.out.println("private Singleton1()");
}
//(3)提供公共的静态方法获取上述的静态成员变量,调用该方法时再new
public static Singleton4 getInstance() {
//在加锁之前进行判断
if(INSTANCE == null) {//一次检索
synchronized (Singleton4.class){
if (INSTANCE == null){//二次检索
INSTANCE=new Singleton4();
}
}
}
return INSTANCE;
}
}

5、懒汉式内部类单例模式

使用内部类的方式可以保证线程安全,建议使用

public class Singleton5 {
//构造私有
private Singleton5(){
System.out.println("private Singleton5()");
}
//创建内部类,在内部类中新建实例
private static class Holder{
static Singleton5 INSTANCE=new Singleton5();
}
private static Singleton5 getInstance(){
return Holder.INSTANCE;
}
}

二、单例模式在jdk中的体现

  • Runtime类是单例模式,饿汉式单例实现
  • System类中的有一个Console类型的cons变量,采用DCL懒汉式方式实现
  • Collections类中有大量单例模式实现,采用内部类懒汉式实现

单例模式五种实现方式以及在JDK中的体现的更多相关文章

  1. LFU五种实现方式,从简单到复杂

    前言 最近刷力扣题,对于我这种 0 基础来说,真的是脑壳疼啊.这个月我估计都是中等和困难题,没有简单题了. 幸好,力扣上有各种大牛给写题解.看着他们行云流水的代码,真的是羡慕不已.让我印象最深刻的就是 ...

  2. iOS开发中数组常用的五种遍历方式

    随着iOS的不断发展,apple也不断推出性能更高的数组遍历方式,下面将对熟悉的五种遍历方式进行列举. 首先定义一个数组,并获取数组长度 NSArray *array=@[",]; NSIn ...

  3. Spring事务Transaction配置的五种注入方式详解

    Spring事务Transaction配置的五种注入方式详解 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学 ...

  4. CacheConcurrencyStrategy五种缓存方式

    CacheConcurrencyStrategy有五种缓存方式:  CacheConcurrencyStrategy.NONE,不适用,默认  CacheConcurrencyStrategy.REA ...

  5. IPC五种通讯方式

    IPC五种通讯方式 1.管道:速度慢,容量有限,只有父子进程能通讯 2.FIFO:任何进程间都能通讯,但速度慢 3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题 ...

  6. CSIC_716_20191129【 单例模式 的五种实现方式】

     单例模式 单例模式:在确定类中的属性和方法不变时,需要反复调用该类的情况.  让所有通过该类实例化出的对象,都指向同一个内存地址. 优点:节省内存空间. 单例模式有五种表现形式: 1.通过class ...

  7. JS 跨域问题常见的五种解决方式

    一.什么是跨域? 要理解跨域问题,就先理解好概念.跨域问题是由于javascript语言安全限制中的同源策略造成的. 简单来说,同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,这里的同一来 ...

  8. Java单例模式几种实现方式

    在平时的工作.学员的学习以及面试过程中,单例模式作为一种常用的设计模式,会经常被面试官问到,甚至笔试会要求学员现场默写,下面将会就单例模式的实现思路和几种常见的实现方式进行简单的分享. 单例模式,是一 ...

  9. Flex页面跳转的五种实现方式

    Flex页面跳转有很多值得学习的地方,本文向大家介绍一下Flex页面跳转的几种方式,主要包括五种方式,这里为大家一一介绍. AD:   在学习Flex的过程中,你可能会遇到Flex页面跳转的概念,这里 ...

  10. JavaScript五种继承方式详解

    本文抄袭仅供学习http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html 一. 构造函数绑定 ...

随机推荐

  1. 【rt-thread】Kconfig文件添加子Kconfig文件时是以顶级Kconfig所在目录为当前路径的

    示例如下 顶级Kconfig文件所在目录 子级Kconfig文件所在目录 子级Kconfig文件添加次子级Kconfig文件,以顶级目录为当前路径依次写出次子级Kconfig文件所在目录

  2. Qt5.9 UI设计(六)——TitleBar功能实现

    前言 上一章介绍了ControlTreeWidget 与ControlTabWidget联动的功能,这一章我们将实现自定义 TitleBar 的功能 操作步骤 修改按键图标最大和最小值 右键按键图标, ...

  3. [转帖]5 分钟学会写一个自己的 Prometheus Exporter

    https://cloud.tencent.com/developer/article/1520621学习一下怎么搭建呢.   去年底我写了一个阿里云云监控的 Prometheus Exporter, ...

  4. [转帖]Jmeter压力测试工具安装及使用教程

    https://www.cnblogs.com/monjeo/p/9330464.html 一.Jmeter下载 进入官网:http://jmeter.apache.org/ 1.第一步进入官网如下图 ...

  5. [转帖]一次SSL握手异常,我发现JDK还有发行版区别

    https://www.cnblogs.com/codelogs/p/16633704.html 原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 最近,我们一个 ...

  6. [转帖]Nginx Ingress 高并发实践

    概述 Nginx Ingress Controller 基于 Nginx 实现了 Kubernetes Ingress API,Nginx 是公认的高性能网关,但如果不对其进行一些参数调优,就不能充分 ...

  7. Linux 一行命令 仅显示某一个网卡的ip地址

    最简答的方法 1. 先使用 ifconfig 查看网卡的设备名 2. 然后输入命令 ifconfig ens192 |grep 'inet ' |cut -d " " -f 10命 ...

  8. 开源IM项目OpenIM 客户端SDK架构剖析-确保消息的有序性,以及消息百分百可达

    开源IM项目OpenIM第二版对于客户端架构进行了局部重构,解决了消息触发时序等bug,也梳理了内部模块.目前已经接近尾声,本文重点讲解SDK架构,以便大家深入了解OpenIM,并希望大家能深度参与开 ...

  9. React中引入外部js文件

    假设需要引入本地的一个jquery库: <script src="http://127.0.0.1:8080/plugins/jquery.min.js" type=&quo ...

  10. Github搜索代码技巧

    ↵相关链接: 码云(gitee)配置SSH密钥 码云gitee创建仓库并用git上传文件 git 上传错误This oplation equires one of the flowi vrsionso ...