单例模式是创建型模式的一种,下面总结一下在 Java 中实现单例模式的几种方法,并在多线程环境中进行了测试。

一、单例模式概念

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供了全局访问的方法。

单例模式的三个特点:

  • 这个类只能有一个实例。
  • 这个类自行创建这个实例。
  • 这个类自行向整个系统提供这个实例。

单例模式的应用有,Windows 里的任务管理器(一个系统中只有一个)、网站计数器(实现多个页面的计数同步)、数据库连接池(减少资源损耗)等。

二、单例模式实现

根据单例模式的特点,我们来实现单例模式,在类中提供一个静态方法来获取这个唯一的实例对象,给其他类提供实例,并且这个实例对象不能直接使用 new 创建,所以构造方法要声明成私有,这便是最简单的单例模式实现。这样的实现在单线程环境中,当然没问题,但是我们还要考虑多线程环境下的安全实现。

下面是对单例模式的各种实现,并且对每种实现方法都在多线程环境中做了测试,所有代码都在我的 GitHub 仓库中中,传送门。该仓库还在完成中,用 Java 实现 23 种设计模式,并对设计原则和每种设计模式做出详细的分析,感兴趣的可以 fork 或者 star 哦,也欢迎小伙伴参与该仓库的完成。

2.1 懒汉式单例类(线程不安全)

通过 getInstance() 方法得到单例对象,单例对象在需要的时候才被延迟创建,所以称之为懒汉式。但是在多线程环境中,由于这个 getInstance() 方法可能被多个线程同时调用,这很可能会创建多个实例,所以这种实现在多线程环境下是不安全的。

2.2 懒汉式单例类(线程安全)

给 getInstance() 加上 synchronized 关键字后,可以保证这个方法在同一时间只能被一个线程调用,多个线程调用这个方法要排队依次调用,这就保证了只会创建一个单例对象,在多线程环境下是安全的。

2.3 饿汉式单例类

相比于上面的懒汉式,饿汉式在类加载的时候就会创建实例对象,在 getInstance() 方法直接返回创建好的对象,简单直接,在多线程环境下也是安全的。

2.4 双重校验锁单例类

针对于上面的线程安全的懒汉式加载,这种实现方式不是直接给方法加上 synchronized 关键字,而是在 getInstance() 方法做双重检查来解决线程不安全的问题。这种方式允许多个线程同时调用该方法,但是在方法中会进行两次检查,第一次检查实例是否已经存在,如果不存在才进入下面的同步代码块,线程安全的创建实例,如果实例真的不存在(避免这是有其他线程创建好了,再次创建新的实例)才会创建实例。这种方式理论上要比直接使用 synchronized 关键字性能要高,但是对于不同虚拟机对 volatile 关键字的优化,优势并不明显。

2.5 静态内部类单例类

创建一个静态内部类,来创建实例,和上面饿汉式相比,虽然都是直接 new 实例,但是这种方式在外部类加载时,静态内部类并不会被加载。只有在第一次调用 getInstance() 方法时,才会显式的加载静态内部类,创建实例,也是一种延迟(懒)创建方式。

2.6 枚举单例类

枚举实现单例模式是 Java 大牛们比较推荐的,因为这种方式实现非常简单,并且这种方式但是大多数单例模式的实现并不是这种方式。这种方式需要开发者对枚举有清晰的认识,这里也简单的回顾一下枚举的基本知识。

枚举是在 Java1.5 之后出现的,可以更加简单的定义常量,通过反编译,我们可以发现枚举其实也是一个 Java 类,这个类继承自 Enum 接口,定义的枚举对象会被加上 static final 关键字,这就是我们不用枚举时声明常量的方式,另外在 static 静态代码块中初始化枚举对象,枚举的构造方法被加上了 private 关键字,防止其他类创建新的枚举对象实例。虽然前面几种方式无法直接使用 new 创建新的实例,但是可以用反射来绕过 private 限制,而枚举却有自带的序列化机制、防止反射攻击造成多次实例化、线程安全的优点,从这些地方我们都可以看出使用枚举是实现单例模式的绝佳方式。

三、单例模式总结

根据对资源加载时机的需要,来选择合适的单例模式实现方式,如果是懒加载方式,可以选择懒汉方式和双重校验锁方式;如果将资源加载的时间提前来达到使用时的快速体验,可以选择饿汉方式;如果涉及到序列化创建单例对象,可以选择枚举方式。

单例模式的优点是提供了对唯一实例的访问控制,可以节约系统资源,但缺点是单例类的职责过重,并且缺少抽象层难以扩展,不太符合单一职责原则。

想看更多编程文章,欢迎关注下方的微信公众号哦。

小司机带你学习单例模式的六种姿势!相关推荐

  1. 小张张带你学习css美化网页,让你在学习的道路上不再孤单

    html里如何使用css来修饰 前言 一.行类式 二.内嵌式 三.外链式 总结 前言 html相当于骨架,css才能给html灵魂和肉体. 一.行类式 行内式又称之为内联式,是通过style属性来设置 ...

  2. 小司机带你撸一个简单的RPC框架

    随着业务的增长,有时候普通的单一型架构不再能满足我们的需求,这就诞生了RPC框架,经过多年的发展,我们可以看到市面上可用性高的开源RPC框架还是比较多的,比如说:Hessian,Dubbo等,这些框架 ...

  3. 小司机带你优雅的实现AOP,IOC

    大多数时候我们使用spring任然是使用XML的配置方式,申明id对应类等等,再依次getBean等等 这个过程比较繁琐且并不美观,那么小编今天带你使用纯注解方式实现AOP, IOC,该技能赶紧get ...

  4. 小司机带你用Java8新特性之方法引用

    基于网上千篇一律的xxx.forEach(System.out::println)示例,不利于初学者理解, 所以小编自己撸了两个示例: 以下代码: package com.demo.java8;pub ...

  5. 小司机带你用Java新特性之Lambda表达式

    最为一名吊丝程序员,那么方法引用以及Lambda表达式这个技能是必须的. 翻了一下网上关于Lambda表达式的示例写的真的是乱七八糟,可阅读性不强 最后小编自己撸了一个最典型的示例,来看一下: pac ...

  6. 小司机带你优雅的初始化Spring容器

    首先定一个接口:StudentDao package com.demo.ioce;public interface StudentDao {public void say(String somethi ...

  7. 【AI学院】有三AI博士小姐姐带你学深度学习之图像识别下篇,附上篇回顾

    带学营第一期(上)圆满结束回顾 有三 AI 深度学习之图像识别带学营第一期(上)圆满结束,这一期我们主要的培训内容是深度学习基础+项目实战(人脸表情识别和鸟类细粒度识别). 以上的课程可以说是干货满满 ...

  8. 手把手带你学习微信小程序 —— 项目实战篇

    微信小程序项目实战篇 WeChat-applet 1.支付宝界面展示 2.微博发帖功能实现 3.时间格式化案例 4.微信红包界面展示 5.微信消息删除案例 6.微信icon 组件 6.1 支付成功界面 ...

  9. 结对编程项目:带UI的小初高数学学习软件——感想及领悟

    结对编程项目:带UI的小初高数学学习软件 用户: 小学.初中和高中学生. 功能: 1.用户注册功能.用户提供手机号码,点击注册将收到一个注册码,用户可使用该注册码完成注册: 2.用户完成注册后,界面提 ...

最新文章

  1. Java:按值传递还是按引用传递详细解说
  2. GET_ROLE_BASED_PAGE_USAGES
  3. 淘宝网的技术发展史(二) ——Oracle替换MySQL
  4. 信号与系统 chapter6 时变与时不变系统
  5. JQuery. Parse XML children recursively. How? - Stack Overflow
  6. Directory /opt/jfrog/artifactory/var has bad permissions for user id 1030
  7. linux文件编码无法修改,在Linux系统中修改文本的字符编码的方法
  8. realme GT2 Pro获3C认证:65W超级快充加持
  9. jquery 读取页面load get post ajax 四种方式代码写法
  10. pandas创建和文件读取笔记(一)
  11. python如何输入多行数据合并_Python如何将多行数据合并成一行|python如何实现excle数据合并...
  12. Scrapy相关命令
  13. 电商企业如何利用CRM突出重围?
  14. ☆【容斥原理】【SCOI2010】幸运数字
  15. js底层原理作用域和作用域链
  16. 4.7 Case Study on Sandy Bridge C…
  17. AutoCAD.NET实现CAD截图
  18. BISHIMIANSHI
  19. 中科柏诚与知名上市公司南天信息(000948)签署战略合作协议
  20. 香农公式和奈氏准则描述的是同一个东西吗?

热门文章

  1. ubuntu切换java版本
  2. @[TOC](CDN防御与高防服务器防御的区别
  3. 在Qt的公式计算中输入常量数值时的注意点
  4. 离散数学 --- 谓词逻辑 --- 谓词符号化与谓词合式公式
  5. 华南师大教授/教育学博士焦建利力荐《正在爆发的互联网革命》
  6. windows10开启wst子系统
  7. Rider去除警告波浪线设置
  8. 赵小楼《天道》《遥远的救世主》解析(3)为什么说肖亚文把丁元英安排到古城是惜缘中的小攀缘?
  9. 36晋级12第十场:九进四
  10. 开源Android 图库