详解单例模式线程安全

单例模式有很多实现方法,饿汉、懒汉、静态内部类、枚举类,每种实现下获取单例对象(即调用 getInstance)时的保证线程安全

  • 饿汉式:类加载就会导致该单实例对象被创建
  • 懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建

实现1: 饿汉式

// 问题1:为什么加 final,防止子类继承后更改
// 问题2:如果实现了序列化接口, 还要做什么来防止反序列化破坏单例,如果进行反序列化的时候会生成新的对象,这样跟单例模式生成的对象是不同的。要解决直接加上readResolve()方法就行了,如下所示
public final class Singleton implements Serializable {// 问题3:为什么设置为私有? 放弃其它类中使用new生成新的实例,是否能防止反射创建新的实例?不能。private Singleton() {}// 问题4:这样初始化是否能保证单例对象创建时的线程安全?没有,这是类变量,是jvm在类加载阶段就进行了初始化,jvm保证了此操作的线程安全性private static final Singleton INSTANCE = new Singleton();// 问题5:为什么提供静态方法而不是直接将 INSTANCE 设置为 public, 说出你知道的理由。//1.提供更好的封装性;2.提供范型的支持public static Singleton getInstance() {return INSTANCE;}public Object readResolve() {return INSTANCE;}
}

实现2: 饿汉式

// 问题1:枚举单例是如何限制实例个数的:创建枚举类的时候就已经定义好了,每个枚举常量其实就是枚举类的一个静态成员变量
// 问题2:枚举单例在创建时是否有并发问题:没有,这是静态成员变量
// 问题3:枚举单例能否被反射破坏单例:不能
// 问题4:枚举单例能否被反序列化破坏单例:枚举类默认实现了序列化接口,枚举类已经考虑到此问题,无需担心破坏单例
// 问题5:枚举单例属于懒汉式还是饿汉式:饿汉式
// 问题6:枚举单例如果希望加入一些单例创建时的初始化逻辑该如何做:加构造方法就行了
enum Singleton {INSTANCE;
}

实现3:懒汉式

public final class Singleton {private Singleton() { }private static Singleton INSTANCE = null;// 分析这里的线程安全, 并说明有什么缺点:synchronized加载静态方法上,可以保证线程安全。缺点就是锁的范围过大,每次访问都会加锁,性能比较低。public static synchronized Singleton getInstance() {if( INSTANCE != null ){return INSTANCE;}INSTANCE = new Singleton();return INSTANCE;}
}

实现4:DCL 懒汉式(双重检验锁)

public final class Singleton {private Singleton() { }// 问题1:解释为什么要加 volatile ?为了防止重排序问题private static volatile Singleton INSTANCE = null;// 问题2:对比实现3, 说出这样做的意义:提高了效率public static Singleton getInstance() {if (INSTANCE != null) {return INSTANCE;}synchronized (Singleton.class) {// 问题3:为什么还要在这里加为空判断, 之前不是判断过了吗?这是为了第一次判断时的并发问题。if (INSTANCE != null) { // t2return INSTANCE;}INSTANCE = new Singleton();return INSTANCE;}}
}

实现5:静态内部类懒汉式

public final class Singleton {private Singleton() { }// 问题1:属于懒汉式还是饿汉式:懒汉式,这是一个静态内部类。类加载本身就是懒惰的,在没有调用getInstance方法时是没有执行LazyHolder内部类的类加载操作的。private static class LazyHolder {static final Singleton INSTANCE = new Singleton();}// 问题2:在创建时是否有并发问题,这是线程安全的,类加载时,jvm保证类加载操作的线程安全public static Singleton getInstance() {return LazyHolder.INSTANCE;}
}

详解单例模式线程安全相关推荐

  1. java 线程一直运行状态_详解JAVA 线程-线程的状态有哪些?它是如何工作的?

    线程(Thread)是并发编程的基础,也是程序执行的最小单元,它依托进程而存在. 一个进程中可以包含多个线程,多线程可以共享一块内存空间和一组系统资源,因此线程之间的切换更加节省资源.更加轻量化,也因 ...

  2. Java多线程详解(线程不安全案例)

    嗨喽-小伙伴们我又来了, 通过前面两章的学习,我们了解了线程的基本概念和创建线程的四种方式. 附上链接: 1.  Java多线程详解(基本概念)​​​​​​​ 2. Java多线程详解(如何创建线程) ...

  3. ThreadPoolExecutor详解及线程池优化

    前言 ThreadPoolExecutor在concurrent包下,是我们最常用的类之一.无论是做大数据的,还是写业务开发,对其透彻的理解以及如何发挥更好的性能,成为了我们在更好的coding道路上 ...

  4. java中断runnable_详解Java 线程中断

    一.前言 大家肯定都使用过 Java 线程开发(Thread / Runnable),启动一个线程的做法通常是: new Thread(new Runnable( @Override public v ...

  5. Java高并发编程详解系列-线程上下文设计模式及ThreadLocal详解

    导语   在之前的分享中提到过一个概念就是线程之间的通信,都知道在线程之间的通信是一件很消耗资源的事情.但是又不得不去做的一件事情.为了保证多线程线程安全就必须进行线程之间的通信,保证每个线程获取到的 ...

  6. java守护线程与用户线程_详解Java线程-守护线程与用户线程

    干java 开发这么多年, 之前一直没留意java 进程还区分守护进程和用户进程.守护进程这个概念最早还是在linux系统中接触的,直到近期使用java开发心跳检测功能时,使用Timer时才发现原来j ...

  7. 一文详解java线程池 详解Java线程池的七个参数 详解池化技术 java如何选择核心线程数 详解Java线程池的拒绝策略

    目录 引言 线程池使用场景 加快请求响应(响应时间优先) 加快处理大任务(吞吐量优先) 特殊说明 线程池的池化技术 线程池的创建 手动创建 创建newFixedThreadPool线程池 创建newS ...

  8. 图文详解 Java线程池

    1.线程池的优势 (1)降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗: (2)提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行: (3) ...

  9. java executors 详解_线程池—Executors 详解

    各位志同道合的朋友们大家好,我是一个一直在一线互联网踩坑十余年的编码爱好者,现在将我们的各种经验以及架构实战分享出来,如果大家喜欢,就关注我,一起将技术学深学透,我会每一篇分享结束都会预告下一专题 线 ...

  10. Java线程详解(11)-线程池

    Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...

最新文章

  1. readonly时禁用删除键,readonly按删除键后页面后退解决方案
  2. (回文串)Manacher算法
  3. svn authz 授权文件模版
  4. 摆脱困境:在每种测试方法之前重置自动增量列
  5. phison主控ps3111量产工具_从固态硬盘拆解看门道 深入解读闪存编号和主控容量...
  6. 如何将mysql的数据库渲染到页面_vue.js实现数据库的JSON数据输出渲染到html页面功能示例...
  7. [BZOJ] 3231: [Sdoi2008]递归数列
  8. 测试交友软件哪个最好用,陌陌与比邻你觉得哪个好用?陌陌比邻两大交友软件对比...
  9. 关于微信中的localStorage及使用cookie的解决方案
  10. java比身高怎么做_D3 Y比例,y对比身高?
  11. python之集合操作 - |
  12. JQUERY-SELECT 实现下拉框可以搜索、选择
  13. 小米路由器 mini 重新刷回官方固件
  14. kafka内外网连接问题
  15. 鹏博士总经理陆榴遭免职 董事称事发突然
  16. bam获取序列_如何从BAM文件中提取fastq
  17. 如何调整DOSBox窗口大小
  18. 【Java Web基础】(五)实现新增下拉列表—由用户输入内容(Html+JS)
  19. 北京搬家货运公司汇总
  20. 美式看跌期权的二叉树定价

热门文章

  1. php数组教程,PHP 数组入门教程小结
  2. Waves 13:一款专业电子音频制作插件和音频信号处理器插件套装
  3. Android网络视频播放器DEMO
  4. My New Game2
  5. 扣丁三国 - 技术支持
  6. 数据库课程设计报告格式模版
  7. 花生壳5.0 for Linux使用教程
  8. 我的数据分析师转型之路,从零到阿里数据分析师
  9. MATLAB 常见取整函数
  10. Java内存模型JMM