Java Singleton类中的线程安全性的示例代码

Singleton是最广泛使用的创建设计模式之一,用于限制应用程序创建对象。在实际应用程序中,数据库连接或企业信息系统(EIS)等资源是有限的,应该明智地使用以避免任何资源紧缩。为此,我们可以实现Singleton设计模式来创建围绕资源的包装类,并将在运行时创建的对象数限制为一个。

Java中的线程安全单例


一般来说,我们按照以下步骤创建一个单例类:

  1. 重写私有构造函数以避免使用new运算符创建任何新对象。
  2. 声明同一个类的私有静态实例
  3. 提供一个公共静态方法,它将返回单例类实例变量。如果未初始化变量,则初始化它,否则只返回实例变量。

使用上面的步骤,我创建了一个单独的类,如下所示:

ASingleton.java


package com.journaldev.designpatterns;public class ASingleton {private static ASingleton instance = null;private ASingleton() {}public static ASingleton getInstance() {if (instance == null) {instance = new ASingleton();}return instance;}}

在上面的代码中,getInstance()方法不是线程安全的。多个线程可以同时访问它,对于前几个线程,当实例变量未初始化时,多个线程可以进入if循环并创建多个实例并打破我们的单例实现。

有三种方法可以实现线程安全。

  1. 在类加载时创建实例变量。

    优点

    • 线程安全无需同步
    • 易于实施

    缺点

    • 早期创建可能未在应用程序中使用的资源。
    • 客户端应用程序无法传递任何参数,因此我们无法重用它。例如,具有用于数据库连接的通用单例类,其中客户端应用程序提供数据库服务器属性。
  2. 同步getInstance()方法

    优点

    • 线程安全性得到保证。
    • 客户端应用可以传递参数
    • 实现了懒惰初始化

    缺点

    • 由于锁定开销导致性能下降。
    • 初始化实例变量后不需要的不必要的同步。
  3. 在if循环和volatile变量中使用synchronized块

    优点

    • 线程安全性得到保证
    • 客户端应用可以传递参数
    • 实现了懒惰初始化
    • 同步开销很小,仅当变量为null时才适用于前几个线程。

    缺点

    • 额外的条件

看看实现线程安全的所有三种方法,我认为第三种方法是最佳选择,在这种情况下,修改后的类将如下所示:


package com.journaldev.designpatterns;public class ASingleton {private static volatile ASingleton instance;private static Object mutex = new Object();private ASingleton() {}public static ASingleton getInstance() {ASingleton result = instance;if (result == null) {synchronized (mutex) {result = instance;if (result == null)instance = result = new ASingleton();}}return result;}}

局部变量result似乎没必要。但它可以提高我们代码的性能。在实例已经初始化的情况下(大多数情况下),volatile字段只被访问一次(由于“return result;”而不是“return instance;”)。这可以将方法的整体性能提高多达25%。

如果您认为有更好的方法可以实现这一点,或者上述实施中的线程安全性受到影响,请发表评论并与我们所有人分享。

更新:String不是用于同步的非常好的候选者,因此我使用Object更新了它,了解有关java中的同步和线程安全的更多信息。

转载来源:https://www.journaldev.com/1827/java-design-patterns-example-tutorial

Java Singleton类中的线程安全性的示例代码相关推荐

  1. Java Singleton类中的线程安全

    Singleton is one of the most widely used creational design pattern to restrict the object created by ...

  2. python停止线程池_详解python中Threadpool线程池任务终止示例代码

    需求 加入我们需要处理一串个位数(0~9),奇数时需要循环打印它:偶数则等待对应时长并完成所有任务:0则是错误,但不需要终止任务,可以自定义一些处理. 关键点 定义func函数处理需求 callbac ...

  3. java继承类大全_Java 面向对象继承部分(示例代码)

    被继承的类称为父类(超类),继承父类的类称为子类(派生类) 通过继承可以实现代码重用 子类拥有父类非 private 的属性.方法. 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展. 子类可以 ...

  4. java并发编程实践(2)线程安全性

    [0]README 0.0)本文部分文字描述转自:"java并发编程实战", 旨在学习"java并发编程实践(2)线程安全性" 的相关知识: 0.1)几个术语( ...

  5. 探究Java File类中list()、listFiles()的使用及区别,认识和使用匿名内部类

    转载自     探究Java File类中list().listFiles()的使用及区别,认识和使用匿名内部类 内容概要: 1.认识File类: 2.File的构造函数: 3.list()及其重载方 ...

  6. java枚举类中字段有没有必要加final____枚举类字段 Field ‘xxx‘ may be ‘final‘

    java枚举类中字段有没有必要加final 今天在写一个系统统一返回码的枚举类时候,突然想到一个问题,当不小心手抖给枚举类自动生成了set方法,而恰巧在用的地方不小心用了set方法,从而修改了code ...

  7. java string.substring 参数,Java,String类中的subString()方法,stringsubstring

    Java,String类中的subString()方法,stringsubstring public class TestStringSubString { // main函数 public stat ...

  8. C++ 如何在类中创建线程

    C++ 如何在类中创建线程 问题描述: 一般我们在启线程时,都是把线程函数写成全局函数来使用,但是如果要把线程操作写成类,线程函数放在类里面在C++编译会不通过. 在C++类中创建线程会有报错: 下面 ...

  9. 纯java pdf转换成html,JAVA实现PDF转HTML文档的示例代码

    本文是基于PDF文档转PNG图片,然后进行图片拼接,拼接后的图片转为base64字符串,然后拼接html文档写入html文件实现PDF文档转HTML文档. 引入Maven依赖 org.apache.p ...

最新文章

  1. 『科学计算』可视化二元正态分布3D科学可视化实战
  2. 实战并发编程 - 03基于不可变模式解决并发问题_1
  3. 重磅解读 | 赵义博:量子密码的绝对安全只存在于理论
  4. 八十四、Python | Leetcode回溯算法系列
  5. 开源 计划管理_公司开源计划的三大好处
  6. Java IO类库之CharArrayWriter
  7. 小例子背后的大道理——Adapter模式详解
  8. JAVA入门[5]-初步搭建SpringMVC站点
  9. iOS 监听锁屏/解锁事件
  10. 小米小爱蓝牙音箱_至今为止功能最全面的「小爱同学」!小米小爱音箱Pro体验...
  11. 航空公司VIP客户查询
  12. 服务器主板128G只显示出64G,[硬件维护]请教高手:新买的160G硬盘为什么分区后就只能显示128G?...
  13. 通过一个简单例子看懂遗传算法,附MATLAB代码
  14. 远比5G发展凶猛!物联网2018白皮书,国内规模已达1.2万亿
  15. 需求分析 - 01外卖配送系统
  16. Maven项目进行打包出现 The POM for xxxx is missing, no dependency information available
  17. 仅需一步,完美解决 0xc000007b 报错
  18. TextCnn原理及实践
  19. Django连接Mysql报错:ModuleNotFoundError: No module named 'MySQLdb'
  20. 怎样写开题报告的PPT讲稿

热门文章

  1. 自适应网页设计(Responsive Web Design)响应式设计
  2. JS操作iframe里的dom
  3. Linux开启路由转发功能
  4. LeetCode 500. Keyboard Row
  5. C++——const加深理解之const在函数后
  6. Julia常用包总结(深度学习、数据科学、绘图...updating...)
  7. 题目1:斐波那契数列(兔子出生规律)
  8. 前端开发 元素的浮动 文字环饶效果 横向排列效果 0229
  9. 前端开发 容器标签 0226
  10. django-模型类字段选项