转载文章:​​​​​​Java单例模式的5种实现方法_明朗晨光的专栏-CSDN博客_单例模式java​​​​​​

饿汉

类加载的时候就创建了实例
优点:类加载的时候创建一次实例,避免了多线程同步问题

缺点:即使单例没被用到也会创建,浪费内存

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

饿汉-变种

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

懒汉-(非线程安全)

优点:需要时才去创建
缺点:没有考虑线程安全问题,多个线程并发调用getInstance,可能会创建多个实例

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

懒汉-(线程安全)

缺点:性能问题,添加了synchronized的函数比一般方法慢得多,若多次调用getInstance,则累积的性能损耗特别大。

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

考虑到以上的性能问题,所以又有一种双重校验锁的实现方式:

双重校验锁

大部分情况下,同步代码块都不会执行到,提高了程序的性能。

有一种情况,两个线程ThreadA,ThreadB,如果threadA执行到了第一个if条件判断,instance = null;ThreadB也执行到了if条件判断instance = null,所以A和B会依次执行同步代码块里的代码。为了避免创建两个实例,因此又在同步代码块里添加了if条件进行二重检验。

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

隐患:

1、此处涉及Java的指令重排优化。指令重排优化是指在不改变原语义的情况下,通过调整指令的执行顺序让程序运行地更快。

2、JVM中没有规定编译器优化的相关内容,也即JVM可以自由地进行指令重排序的优化。

3、此问题的关键在于由于指令重排序优化的存在,导致初始化Singleton和将对象地址赋给instance字段的顺序是不确定的。

4、在某个线程创建单例对象时,在构造函数被调用前,就为该对象分配了内存空间并将对象的字段设置为默认值。此时就可以将分配的内存地址赋值给instance字段了,然而该对象可能还没初始化。若紧接着另一个线程来调用getInstance,获取到的就是状态不正确的对象,程序出错。

JDK5的修正:以上是双重校验锁失效的原因,不过在JDK1.5之后的版本添加了volatile关键字。

1、volatile的一个语义是禁止指令重排序优化,也就保证了instance变量被赋值的时候对象已经是初始化过的,从而避免了上述问题。

2、Java中的volatile变量是什么?

(1)关键字的作用有两个:

①多线程主要围绕可见性和原子性两个特性展开,使用volatile关键字修饰的变量,保证了其在多线程之间的可见性,即每次读取到的volatile变量,一定是最新的数据。

②代码底层执行的顺序是Java代码-->字节码-->根据字节码执行对应的C/C++代码-->C/C++代码被编译成汇编语言-->和硬件电路交互。实际中,为了获取更好的性能,JVM可能会对指令进行重排序,多线程下可能会出现一些意想不到的问题。使用volatile则会禁止语义重排序,也一定程度上降低了代码执行效率。实践角度而言,volatile的一个重要作用就是和CAS结合,保证了原子性。

(2)volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其他线程是透明的。volatile变量可以保证下一个读取操作会在前一个写操作之后发生。

代码如下:

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

静态内部类

public class StaticSingleton {private StaticSingleton() {}private static class SingletonHolder {private static StaticSingleton INSTANCE = new StaticSingleton();}public static StaticSingleton getInstance() {return SingletonHolder.INSTANCE;}
}

枚举


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

既能避免多线程同步问题,又能防止反序列化重新创建新的对象。

————————————————
版权声明:本文为CSDN博主「明朗晨光」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011386173/article/details/82454714

sheng的学习笔记-设计模式-单例模式相关推荐

  1. sheng的学习笔记-设计模式-代理模式

    原理图: 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 至少在以下集中情况下可以用 ...

  2. sheng的学习笔记-平衡二叉树(AVL)和3+4重构

    二叉树细节可参考: sheng的学习笔记-二叉树(BST)_coldstarry的博客-CSDN博客 定义 平衡二叉树,又称AVL树,用于解决二叉排序树高度不确定的情况,如果二叉排序树的子树间的高度相 ...

  3. sheng的学习笔记-Vector源码分析

    概述 Vector底层也是数组,跟ArrayList很像(先看下ArrayList,再看Vector会很轻松),ArrayList可参考下文,并且由于效率低,已经被淘汰了,大概瞅瞅得了 sheng的学 ...

  4. sheng的学习笔记-kafka框架原理

    目录 环境搭建 下载安装包 修改配置文件 启动服务 创建topic 生产消息 消费消息 代码 maven配置 kafka的生产者代码 消费者代码 基础知识 主题TOPIC: 单播和多播 单播消息: 多 ...

  5. [学习笔记]设计模式之Command

    为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 在上篇Chain of Responsibility(职责链)模式笔记中,我们学习了一种行为型设计模式.今天,我们继续这一主题,来学习 ...

  6. [学习笔记]设计模式之Decorator

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 Decorator(装饰)模式,可以动态地给一个对象添加一些额外的职能.为了更好地理解这个模式,我们将时间线拉回Bridge模式笔记的 ...

  7. 设计模式学习笔记(1)——单例模式

    单例模式是常用的设计模式之一,作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,特点: 某个类只能有一个实例,避免重复实例化. 必须自行创建这个实例,不允许 ...

  8. Java设计模式学习笔记:单例模式(一)

    今天学到单例模式,对几种单例模式的特点做了一次梳理,从线程安全性和性能两个方面来说. 首先都知道有两种最常见的单例模式:饿汉式和懒汉式,如下: 饿汉式: public class Hangry() { ...

  9. sheng的学习笔记-redis框架原理

    摘要:redis命令,使用场景,持久化,缓存穿透,缓存雪崩,缓存击穿,持久化(RDB,AOF),事务,锁,集群,主从复制原理,哨兵模式 目录 基础知识 简介: 安装: Windows 下安装 Linu ...

最新文章

  1. gridview格式化日期字段
  2. 基于NMAP日志文件的暴力破解工具BruteSpray
  3. legend3---3、lavarel页面post请求错误之后跳转
  4. h3c服务器安装linux,H3C服务器安装Ubuntu操作系统
  5. 3目标检测的准确率_吊打YOLOv3!普林斯顿大学提出:CornerNetLite,基于关键点的实时且精度高的目标检测算法,已开源!...
  6. 学会拐弯,才是人生大智慧(深度好文)
  7. python o创建文件_Python 文件I/O
  8. matplotlib+numpy绘制二维条形直方图
  9. Centre Consortium 发布了USDC 智能合约 2.1 版本
  10. eNSP使用介绍,VRP基础配置(2017年12月18日 17:43:53)
  11. 20150401--Dede+搜索页面,评论
  12. 【硬核课】最新《图卷积神经网络GCN》2020概述,76页ppt,NTU-Xavier Bresson,纽约大学深度学习课程...
  13. MySql入门基础讲解
  14. html table 表头停留,HTML table固定表头
  15. 计算机word的关闭怎么办,电脑无法打开Word提示已停止工作并自动退出怎么办
  16. 计算机二级错误503,503错误的服务器要怎么解决教程
  17. JS设置浏览器缩放比例
  18. Go语言核心之美 1.4-包和文件
  19. pcl_viewer的使用
  20. SYN包含的常用TCP选项

热门文章

  1. 雪王刚启用,1000多家加盟商抵制,说太累了low
  2. 量子计算机到底神在哪里说明文,说明文专题专项训练题(26页)-原创力文档
  3. 软件测试方法与测试策略
  4. 分享一套抖音特别火的圣诞树源代码
  5. notepad++ 下载地址(非官网,无捆绑插件,自己记录一下)
  6. javascript(JS与css交互)详细介绍
  7. ubuntu下LaTeX的中文输入法与中文配置
  8. [ 深度学习平台 ] —— Google Colab : 开源GPU的配置与使用
  9. 58同城上市半年股价沉浮录
  10. 高质量PM,都用哪些优质的开源项目管理工具