java static 单例模式_Java 单例模式全面学习

介绍

什么是单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点

解决什么问题:省略创建对象所花费的时间,不需要频繁创建对象,减轻 GC 压力。

单例模式有以下几种实现方式:

懒汉式第一次使用的时候才进行加载

// 非线程安全

public class Singleton {

private Singleton(){}

private static Singleton singleton;

public static Singleton getSingleton(){

if (singleton == null){

singleton = new Singleton();

}

return singleton;

}

}

// 加锁线程安全,但是每次获取都会加锁判断

public class Singleton {

private Singleton(){}

private static Singleton singleton;

public static synchronized Singleton getSingleton(){

if (singleton == null){

singleton = new Singleton();

}

return singleton;

}

}

饿汉式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。

通过类加载机制保证单例,但是如果代码中有其它方式导致类加载(反射、反序列化),就不满足单例

public class Singleton {

public static Singleton singleton = new Singleton();

private Singleton(){}

public static getSingleton() {

return singleton;

}

}

双重校验(double check)

public class Singleton {

private Singleton(){}

public static volatile Singleton singleton;

public static getSingleton(){

if (singleton == null){

synchronized(Singleton.class){

if (singleton == null){

singleton = new Singleton();

}

}

}

return singleton;

}

}第一次校验 singleton 是否为空,是为了提高代码执行效率。单例模式只创建一次,后面调用就不用加锁直接返回已创建的实例。

第二次校验 singleton 是否为空,是防止二次创建实例。线程 A 、线程 B 同时进入第一个判断之后,线程 B 拿到锁创建了实例,然后线程 A 拿到锁之后如果不加以判断,就会再次创建实例。

singleton 用 volatile 修饰是为了防止 JVM 指令重排序。singleton = new Singleton() 分为以下 3 步,步骤 3 可能在步骤 2 之前执行,此时另外的线程发现 singleton 不为 null,直接跳过第一个判断,返回未初始化完全的对象就会出问题。分配内存空间

初始化对象

内存空间赋值给对应的引用

静态内部类

public class Singleton {

private Singleton (){}

private static class SingletonHolder {

private static final Singleton INSTANCE = new Singleton();

}

public static final Singleton getSingleton(){

return SingletonHolder.INSTANCE;

}

}满足延迟加载:Singleton 类被装载了,instance 不一定被初始化,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类。对于类的初始化,虚拟机规范则严格规定了有且只有四种情况必须立即对类进行初始化,遇到 new、getStatic、putStatic 或 invokeStatic 这 4 条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。

生成这4条指令最常见的 java 代码场景是:

1)使用 new 关键字实例化对象

2)读取一个类的静态字段(被final修饰、已在编译期把结果放在常量池的静态字段除外)

3)设置一个类的静态字段(被final修饰、已在编译期把结果放在常量池的静态字段除外)

4)调用一个类的静态方法

执行类的初始化期间,JVM 会获取一个锁,同步多个线程对同一个类的初始化,所以可以保证线程安全

这种方式只适用于静态域的情况,静态内部类只能访问外部类的静态成员变量。

枚举

public enum Singleton {

INSTANCE;

public void doSomeThing() {

}

}

参考双重检查锁定与延迟初始化-InfoQ​www.infoq.cn面试官所认为的单例模式 - 掘金​juejin.im

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

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

相关文章

sql 没有调试 菜单_MySQL递归查询上下级菜单

正文在传统的后台管理系统里面经常会需要展示多级菜单关系,今天我们来学一下如何使用一条SQL语句展示多级菜单。现在我们有一张corpinfo单位表,里面有一个belong字段指向上级单位,首先来看一下现在表里有什么数据:SELECT uid,ubel…

java 桥 word_java导出word的6种方式(转发)

最近做的项目,需要将一些信息导出到word中。在网上找了好多解决方案,现在将这几天的总结分享一下。目前来看,java导出word大致有6种解决方案:1:Jacob是Java-COM Bridge的缩写,它在Java与微软的COM组件之间构…

python删除指定天数前的文件_python 删除指定时间间隔之前的文件实例

遍历指定文件夹下的文件,根据文件后缀名,获取指定类型的文件列表;根据文件列表里的文件路径,逐个获取文件属性里的“修改时间”,如果“修改时间”与“系统当前时间”差值大于某个值,则删除该文件。#!/usr/b…

jieba 词典 词频_在Hanlp词典和jieba词典中手动添加未登录词

在使用Hanlp词典或者jieba词典进行分词的时候,会出现分词不准的情况,原因是内置词典中并没有收录当前这个词,也就是我们所说的未登录词,只要把这个词加入到内置词典中就可以解决类似问题,如何操作呢,下面我…

android访问java服务器_Android_post访问java服务器端

//javaee工程访问地址String url "http://localhost:8080/TestAndroid";//把要请求的值封装到namevalupair的集合中NameValuePair nameValuePair1 new BasicNameValuePair("name","zhangsna");NameValuePair nameValuePair2 new BasicNameVal…

pythonweb啥意思_python-web-guide

Python Web 入坑指南____ _ _ __ __ _ ____ _ _| _ \ _ _| |_| |__ ___ _ __ \ \ / /__| |__ / ___|_ _(_) __| | ___| |_) | | | | __| _ \ / _ \| _ \ \ \ /\ / / _ \ _ \ | | _| | | | |/ _ |/ _ \| __/| |_| | |_| | | | (_) | | | | \ V V / __/ |_) | | |_| | |_| | | (_…

java范例_Java范例集锦(一)

范例1:不用其他变量实现两个变量通常在对变量互换时,将创建一个临时变量来共同完成互换,临时变量的互换增加了系统资源的消耗。如果需要交换的是两个整数类型的变量,则可以使用异或运算符(^)进行更高效的处理。实现代码如下&#…

python查找输出文字_Python基础练习,查询文本内容并输出;

1、编写可供用户查询的员工信息表:1).用户认证(输入用户名,密码)2).查询关键字:姓名3).显示ID,name,section,phone4).员工信息表内容如下:cat search_name.txt001wenlong IT12345678002xiaojun …

python列表索引超出范围 等于啥_python - IndexError:列表分配索引超出范围,Python

我正在尝试实现功能。它的工作方式应该是这样的:它需要两个列表。标记一些索引,最好居中。父母双方都切换标记索引。其他索引按顺序转到其父元素。如果该父元素中已经存在相同的元素,则它将映射并检查同一元素在其他父元素的位置并到达那里。…

python爬取汽车之家_python爬取 汽车之家(汽车授权经销商)

一:爬虫的目标:打开汽车之家的链接:https://www.autohome.com.cn/beijing/,出现如下页面我们的目标是点击找车,然后出现如下图我们要把图中的信息抓取到二:实现过程我们选择 宝马5系 然后点击找车注意宝马…

python跨目录调用_python 跨目录访问文件

1.同级、同目录的文件之间的访问有这样一个目录结构假如,in_A.py 这个文件想调用 hello_world.py 中的函数怎么办呢? --->>> import只需在 in_A.py 中 写入importhello_worldhello_world.functions()这样就可以访问啦,什么原理呢&a…

Java 调用 Caffe_解决 free(): invalid pointer: 0x00000000019ff700 运行时报错(caffe)(libtool使用)...

编译成功,运行时报错:在使用 pytorch or tensorflow or caffe 时,都可能存在这个问题:*** Error in xxx: free(): invalid pointer: 0x00000000020663b0 ***很可能是缺少libtcmalloc库解决方法1:apt-get安装libtcmallo…

unity 世界坐标间角度_Unity学习笔记—本地坐标转世界坐标

核心用到的方法就是transform.TransformPoint( )这个方法的返回值就是Vector3类型的世界坐标,transform就是相对的物体,括号里的就是相对这个transform的本地坐标,比方说我现在的位置吧,知道我相对于我的邻居的坐标:Pos1&#xff…

python访问序列元素的编号用什么括起来_python-重新编号数组中元素的有效方法...

我是python的新手,正在尝试实现一种遗传算法,但需要其中一项操作的代码方面的帮助.我是这样提出问题的:>每个人我都由一串M个整数表示> I中的每个元素e取值从0到N> 0到N之间的每个数字都必须在I中至少出现一次> e的值并不重要,只要每个唯一值元素采用相…

java 下载代码_实现文件下载的java代码

实现文件下载的java代码//这是实现下载类(servlet),详细思路代码例如以下://也可连接数据库package com.message;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;import java.util.*;public class FileDownServlet extends HttpS…

webcomponents安装了没有用_Web Components 入门实例教程

来源 | http://www.ruanyifeng.com/blog/2019/08/web_components.html组件是前端的发展方向,现在流行的React和Vue都是组件框架。谷歌公司由于掌握了Chrome浏览器,一直在推动浏览器的原生组件,即Web组件API。部分第三方框架,原生组…

虹软java接摄像头_虹软人脸识别SDK(java+linux/window) 初试

虹软人脸识别全平台demo调用—快速上手之服务端Windows篇demo名称:ArcFace 2.2 Windows(86) Demo [C]一 环境配置:1) 安装VS2013环境安装包(vcredist_x86_vs2013.exe)2) 从官网(http://www.arcsoft.com.cn/ai/arcface.html)申请sdk,下载对应的…

python中re_Python中re(正则表达式)模块学习

今天学习了Python中有关正则表达式的知识。关于正则表达式的语法,不作过多解释,网上有许多学习的资料。这里主要介绍Python中常用的正则表达式处理函数。re.matchre.match 尝试从字符串的开始匹配一个模式,如:下面的例子匹配第一个…

java ee 上传文件_17.《JavaEE 学习笔记》Servlet 上传文件

功能介绍:利用 Servlet 和表单提交,选择本地文件上传到服务器。上传的文件可以是文本文件或图像文件或任何文档,不能是文件夹。需要引入的 jar 文件:commons-fileupload-1.3.2、commons-io-2.5.jar。下载链接:将下载好…

spark python 上传代码包_使用 Livy Rest API 提交 spark 批量任务 (jar,Python, streaming)...

Livy是一个开源的REST 接口,用于与Spark进行交互,它同时支持提交执行代码段和完整的程序。image.pngLivy封装了spark-submit并支持远端执行。启动服务器执行以下命令,启动livy服务器。./bin/livy-server这里假设spark使用yarn模式&#xff0c…