近半年来,我面试了大概100多个Java后端程序员,线程安全的单例模式也是最常问到的一个问题。那么看看大家都是怎么样回答的呢。

第一种:不考虑线程安全的单例

/**

一般初级的Java程序员会这么写,该单例模式中没有使用同步块,但是具备了单例模式的基本特征:

  1. 构造函数私有
  2. 静态成员变量
  3. 静态函数返回实例

第二种:饿汉式

/**

由于ClassLoader的加载机制,饿汉式保证了singleton变量只会被初始化一次。instance在类装载时就实例化,虽然导致类装载的原因有很多种,例如存在多个静态方法,这时候初始化instance就没有懒加载的效果。经测试,在只有一个getInstance静态方法时,构造函数也只有在我调用getInstance()的时候才初始化,实际也是懒加载效果。这个也是回答的比较多的一个。

修改原有的构造函数添加打印输出

private 

测试类

@RunWith

输出:

Sleeping for 2 seconds...
Accessing class...
class com.eappcat.blog.singleton.s2.Singleton
Sleeping for 2 seconds...
Accessing getInstance()...
22222
com.eappcat.blog.singleton.s2.Singleton@66cd51c3

第三种:懒汉式

/**

懒汉式通过synchrinized关键词保证了singleton只会被初始化一次。但是synchrinized在多线程下会等待锁,降低性能。

第四种:懒汉式改进

/**

双重锁校验涉及到JVM的指令重排,volatile,synchronized等综合知识。成员变量上的volatile,两个null检查,以及synchronized都不能少,面试中经常有人会忽略volatile修饰词,或者不能解释为啥必须要这么写。

volatile保证了该变量对多线程的可见性,synchronized代码块完成,立即刷新singleton到其他线程的内存区域。

synchronized负责对构造加锁,保证实例只被初始化一次。

双重锁的第一重解决的大多数情况下获取变量不需要等待同步锁的问题,第二重检查保证了singleton不被初始化两次。

有关volatile,synchronized等知识我们会在后续的内容详细解释。

第五种:静态内部类

/**

定义一个私有的内部类,在第一次用这个嵌套类时,会创建一个实例。而类型为SingletonHolder的类,只有在Singleton.getInstance()中调用,由于私有的属性,他人无法使用SingletonHolder,不调用Singleton.getInstance()就不会创建实例。
优点:达到了lazy loading的效果,即按需创建实例。

第六种:枚举单例

/**

最简单的单例实现,也是java编程思想作者推荐的单例模式实现方式。解决了懒加载(同第二种),线程安全和序列化的问题。

综上所述,第二,第五,第六种单例模式是比较推荐的,区区一个小小的单例还真的是不简单。

相关源代码

java 单例模式_谈谈Java中的单例模式相关推荐

  1. java面向对象_谈谈Java的面向对象

    类的拷贝和构造 C++是默认具有拷贝语义的,对于没有拷贝运算符和拷贝构造函数的类,可以直接进行二进制拷贝,但是Java并不天生支持深拷贝,它的拷贝只是拷贝在堆上的地址,不同的变量引用的是堆上的同一个对 ...

  2. java 节假日_谈谈JAVA实现节假日验证

    原标题:谈谈JAVA实现节假日验证 我们需要两个类,第一个类: 我们叫它验证类. 第二个类: 它是对法定节假日的抽象. 第一步开始: 当验证类被初始化的时候,会加载本年的所有法定节假日到一个list里 ...

  3. java装箱_谈谈Java的自动装箱和拆箱

    Java作为面向对象语言,有人认为所看到的都是对象,事实上,在Java SE 5之前,基本类型默认并不是采用对象存在的如果您想要把基本类型作为对象来处理,就必须自行转换,不过,在Java SE 5之后 ...

  4. linux java 栈_关于Java中栈与堆的思考

    1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度比堆要快,仅次于直接位于C ...

  5. java多核并行计算_谈谈Java任务的并行处理

    前言 谈到并行,我们可能最先想到的是线程,多个线程一起运行,来提高我们系统的整体处理速度:为什么使用多个线程就能提高处理速度,因为现在计算机普遍都是多核处理器,我们需要充分利用cpu资源:如果站的更高 ...

  6. java stream 求和_谈谈Java任务的并行处理

    作者:ksfzhaohui 前言 谈到并行,我们可能最先想到的是线程,多个线程一起运行,来提高我们系统的整体处理速度:为什么使用多个线程就能提高处理速度,因为现在计算机普遍都是多核处理器,我们需要充分 ...

  7. java 单元测试_在springboot中写单元测试解决依赖注入和执行后事务回滚问题

    往期文章 「Java并发编程」谈谈Java中的内存模型JMM 面试官:说说你知道多少种线程池拒绝策略 为什么不要在MySQL中使用UTF-8编码方式 前言 很多公司都有写单元测试的硬性要求,在提交代码 ...

  8. c 与java 反射性能_谈谈Java 反射的快慢

    [相关学习推荐:java基础教程] 反射到底是好是坏 说到Java 中的反射,初学者在刚刚接触到反射的各种高级特性时,往往表示十分兴奋,甚至会在一些不需要使用反射的场景中强行使用反射来「炫技」.而经验 ...

  9. java short long_谈谈Java中整数类型(short int long)的存储方式

    在java中的整数类型有四种,分别是 byte  short int long 其中byte只有一个字节 0或1,在此不详细讲解. 其他的三种类型如下: 1. 基本类型:short 二进制位数:16 ...

  10. js 中 java 代码_在js中嵌套java代码

    jsp中有时候在js中操作某些java后台传递过来的数据逻辑比较复杂,比如list内容的遍历,可以直接在页面上添加java脚本来执行内容,代码如下: //在js中插入java代码操作 //取出java ...

最新文章

  1. SQL Server 性能基线和监控
  2. C++继承和派生简明教程
  3. WCF 客户端代理生成 通过SvcUtil.exe
  4. k8s minikube部署hbase
  5. 【git】强制覆盖本地代码(与git远程仓库保持一致)
  6. socket模拟http的登陆_python模拟登陆知乎(最新版)
  7. 小程序开发(10)-之热力图解决方案、手绘图
  8. C++设计模式-桥接模式
  9. python适用的操作系统是什么_学习Python一般使用什么操作系统?
  10. iOS设置UITableView的背景图片,以及不显示多余的空Cell
  11. paip.c#使用匿名函数建立委托提高可读性
  12. wex5 java_[Java教程]WEX5中ajax跨域访问的几种方式
  13. 【数据分析系列】Python数据预处理总结篇
  14. 计算机代码画玫瑰,turtle画玫瑰花(示例代码)
  15. Educational Codeforces Round 118 (Rated for Div. 2)
  16. html5qq空间代码作业,免费QQ空间背景代码大全(高手整理)
  17. IPv4编址;A类、B类、C类、D类、E类IP地址(IP地址;网络地址和主机地址;子网掩码;网关;广播地址;)
  18. walsh64码 matlab,实验7 Walsh码及单用户CDMA系统直接序列扩频仿真
  19. 基于MATLAB机器视觉技术的水果分级研究进展
  20. windows配置环境变量和path环境后即时生效

热门文章

  1. 树莓派4B Ubuntu20.04 ROS2 DSO realsense d455
  2. 前端学习笔记系列一:2 Vue的单文件组件
  3. qt qml fuzzyPanel 毛玻璃效果
  4. PHP中获取html页面传值
  5. 怎样关闭eclipse中的tooltip提示
  6. 【电脑硬件问题】视频接口和显示器偏色
  7. 排序算法专题-希尔排序
  8. 决策树的简单实现与可视化
  9. ArcGIS 城市生活区用地适宜性评价(三)
  10. 遥感动态监测实验(以福州为例)