java 单例 实现_java 实现单例的各种方式

概述

上一篇日志中,我们介绍了单例模式的概念和基础的应用

本节中,我们就来介绍一下 java 语言中如何编写单例模式类

只适合单线程环境的单例模式

public class Singleton {

private static Singleton instance = null;

private Singleton() { }

public static Singleton getInstance(){

if (instance == null) {

instance = new Singleton();

}

return instance;

}

}

这是单例模式的最简单实现,private 的构造方法保证了类不会被通过 new 的方式创建,同时,判断 instance 是否为 null 保证了单线程环境下单例模式运行的正确性

但是,正如我们反复强调的,这种方式是非线程安全的,原因在于,当多个线程并发执行,同时进行判断 instance 为 null 的操作,而此时 instance 确实为 null,那么所有的线程都将去创建一个单例的对象,这显然是我们不希望看到的,那么下面我们就来解决这个问题

通过同步锁实现线程安全

正如上面提到的,之所以存在线程安全问题,主要是因为判断 instance 是否为 null 与对象的创建是非原子性的,那么,我们只需要用锁来保证两个操作的原子性即可解决这个问题

public class Singleton {

private static Singleton instance = null;

private Singleton() { }

public static synchronized Singleton getInstance() {

if (instance == null) {

instance = new Singleton();

}

return instance;

}

}

但是加锁对性能是会造成影响的,在并发环境下,当一个线程运行到 synchronized 处,获取锁进入到 instance 的判断,其他所有的并发线程都必须在该线程执行完 instance 的创建操作后才能够继续执行,而事实上,一旦 instance 被创建,这样的等待都将会是白费的

双重校验锁

双重校验锁对上面的例子进行了优化

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;

}

}

一旦对象被创建,那么程序将不会去请求获取锁而是直接返回 instance

最简单的线程安全单例模式

public class Singleton {

private static Singleton instance = new Singleton();

private Singleton() { }

public static Singleton getInstance() {

return instance;

}

}

这段代码看上去非常简单,他会在类首次被加载时创建单例的对象,jvm 会保证单例对象只被创建一次,但是有时我们仅仅是在代码中引用了这个类,或者仅仅调用了这个类中的其他方法,我们并不希望在我们还不需要通过 getInstance 方法获取对象的时候,对象就已经被创建了,这是这种方式的主要问题

静态内部类

public class Singleton {

private Singleton() {

}

private static class SingletonHolder {

private final static Singleton instance = new Singleton();

}

public static Singleton getInstance() {

return SingletonHolder.instance;

}

}

这种方式解决了上一种方式所存在的问题,仅在 getInstance 方法被调用时,对象才会被创建

使用枚举

public enum SingletonEnum {

BOOM_MAZE_FACTORY(new BoomMazeFactory()),

STANDARD_MAZE_FACTORY(new StandardMazeFactory()),

;

private MazeFactory mazeFactory;

public MazeFactory getMazeFactory() {

return mazeFactory;

}

SingletonEnum(MazeFactory mazeFactory) {

this.mazeFactory = mazeFactory;

}

}

由于枚举在项目中并不会被常常用到,这样的用法就更加难得一见了,而事实上,这才是最推荐的用法

微信公众号

欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤

标签

技术帖

技术分享

java

singleton

设计模式

模式

设计

单例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339418.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Drools DMN最新开源引擎性能改进

我们一直在寻求改善Drools DMN开源引擎的性能。 我们最近审查了DMN用例,其中输入数据节点的实际输入总体有所不同。 这突出显示了引擎的次佳性能,我们在最新版本中对此进行了改进。 我想分享我们的发现! 基准制定 当我们开始为该用例运行一个…

今晚课题:2019-3-23

今晚课题剖析《服务器高并发-IOCP模型架构》上课时间:2019/03/23 20:30--22:30授课讲师:杰越教育C/C学院--Vico课程链接:https://ke.qq.com/course/353889?tuin7472c9c 课程内容: 1、C/C编程语言入门精通 2、C线程技术在服务器…

使用Selenium WebDriver测试自动化的22条实用技巧

使用Selenium进行测试自动化已使全球的网站测试人员能够轻松执行自动化的网站测试。 Webdriver是Selenium框架的核心组件,通过它您可以针对不同类型的浏览器(例如Google Chrome,Mozilla Firefox,Safari,Opera&#xff…

java编译源文件_Java源文件编译示例

java程序编译java源文件JavacCompile文件:package yan.demo.javac;import java.io.File;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import javax.tools.Diagnostic;import javax.tools.DiagnosticCollector;import javax.tools.Fi…

这么奇葩搞笑的代码注释你见过吗

程序员作为一种“异类”,虽然他们平时给人们的留下的印象并不太好,觉得他们只会写代码。但是有的时候不得不佩服他们天马行空的想象力,他们可能会利用注释让你噗嗤一笑,下面我们来看看那些奇葩搞笑的代码注释吧。注释1&#xff1a…

facelets_不要在facelets中重复表情

facelets您是否曾经在JSF中看到过像这样的重复EL表达式&#xff1f; <h:inputText value"#{oneBean.name}" rendered"#{anotherBean.showPerson}"/> <h:inputText value"#{oneBean.birthday}" rendered"#{anotherBean.showPerson…

C语言与Java的深情对话:儿子,还得多练几年啊!老子还是老子

很多小伙伴都老是会碰到疑问&#xff0c;其实还是基础没打扎实&#xff0c;这些题如果你不看答案你能知道多少呢&#xff1f;如果还有很多不知道就证明基础没打扎实&#xff0c;如果你还在入门纠结&#xff0c;如果你还在苦恼怎么入门&#xff01;小编有个建议&#xff0c;可以…

Servlet和JSP之间的区别

JSP和Servlet都是与使用Java构建基于Web的应用程序有关的重要概念。 基本上&#xff0c;Servlet是Java中HTML&#xff0c;而JSP是HTML中的Java。 任何典型的Web开发面试都可能有几个基于JSP和Servlet的Java面试问题 。 尽管JSP和Servlet的主要目的是相同的&#xff0c;但是两者…

BAT人脸识别功能第二步-人脸检测

今晚课题点击【阅读原文】或长按图片【识别图中的二维码】即可参加今晚的课程。

java emptylist_Java之Collections.emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方...

先说明一下好处有哪些&#xff1a;1&#xff0c;如果你想 new 一个空的 List &#xff0c;而这个 List 以后也不会再添加元素&#xff0c;那么就用 Collections.emptyList() 好了。new ArrayList() 或者 new LinkedList() 在创建的时候有会有初始大小&#xff0c;多少会占用一内…

java中插入排序实例_java中对插入排序的理解以及实例

一、基本思想通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从后向前扫描&#xff0c;找到相应的位置并插入。插入排序非常类似于整扑克牌。在开始摸牌时&#xff0c;左手是空的&#xff0c;牌面朝下放在桌上。接着&#xff0c;一次从桌上摸起一张牌&a…

hazelcast入门教程_Hazelcast入门指南第3部分

hazelcast入门教程这是从初学者的角度来看一系列有关如何使用Hazelcast的文章的延续。 如果您还没有阅读最后两个&#xff0c;我鼓励阅读它们&#xff1a; Hazelcast入门指南第1部分 Hazelcast入门指南第2部分 原始人来了 在上一篇文章中&#xff0c;我提到将ILock与IList和…

经典游戏底层框架--迷宫游戏构成原理剖析

今晚课题点击【阅读原文】或长按图片【识别图中的二维码】即可参加今晚的课程。

突破100万年薪《多线程服务器端架构》

今晚课题点击【阅读原文】或长按图片【识别图中的二维码】即可参加今晚的课程。

Java中的观察者设计模式

在本教程中&#xff0c;我们将讨论Observer设计模式。 观察者模式有两个主要方面- 主题和观察者 。 当我们的系统有多个对象&#xff08;称为观察者&#xff09;时 &#xff0c;将使用一个模式&#xff0c;该对象依赖于一个特定对象&#xff08; 主体&#xff09;的状态 。 所…

java class api 中文乱码_SpringMVC之springmvc原始api,请求中文乱码问题

先搞一波效果图1.Controllerpackage com.tz.controller;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import org.springframework.beans.factory.annotation.Required;import org.springframe…

从流水线工人,到谷歌上班的程序媛

非科班、转行当程序员的励志故事有很多&#xff0c;我们在 8 年前扩散分享过一个国外的故事&#xff1a;我来自于一个东欧国家。我在一个煤矿里工作了很多年&#xff08;在一个很深的矿井里&#xff09;。每天我都处在危险中&#xff0c;那些年都是这样度过的。后来我感觉过够了…

jpa 实体映射视图_JPA教程:实体映射-第2部分

jpa 实体映射视图在上一篇文章中&#xff0c;我展示了一种持久保存实体的简单方法。 我解释了JPA用于确定实体默认表的默认方法。 假设我们要覆盖此默认名称。 我们之所以喜欢这样做&#xff0c;是因为数据模型是以前设计和修复的&#xff0c;并且表名与我们的类名不匹配&#…

java顺序栈和链栈_Java的顺序栈和链式栈

栈的定义栈是限制在表的一段进行插入和删除的运算的线性表&#xff0c;通常能够将插入、删除的一端为栈顶&#xff0c;例外一端称为栈底&#xff0c;当表中没有任何元素的时候称为空栈。通常删除(又称“退栈”)叫做弹出pop操作&#xff0c;每次删除的都是栈顶最新的元素&#x…

Java:ChronicleMap第2部分,超级RAM映射

诸如无处不在的HashMap类的标准Java Map最终受到可用RAM的限制。 阅读本文并了解如何创建几乎无限大小甚至超过目标计算机的RAM大小的Java Map。 内置的Map实现&#xff0c;例如HashMap和ConcurrentHashMap &#xff0c;只要它们相对较小&#xff0c;就可以正常工作。 在所有情…