基于Java利用static实现单例模式
作者:灵剑山真人 发布时间:2021-12-20 06:07:32
一、之前旧的写法
class Singleton{
private Singleton() {}
private static Singleton instance = null;
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
就利用Sington.getInstace
就可以了,获得的是同一个实例。
上面那个代码有两个优点:
懒加载,把在堆创建实例这个行为延迟到类的使用时。
锁效果,防止生成多个实例,因为
synchronized
修饰这个static
方法,所以相当于给这个方法加上了一个类锁🔒。
二、static代码块的效果
先来看一段代码:
class StaticClass{
private static int a = 1;
static{
System.out.println("语句1");
System.out.println("语句2");
}
static{
System.out.println("语句3");
System.out.println("语句4");
}
}
当在多个线程同时触发类的初始化过程的时候(在初始化过程,类的static变量会被赋值为JVM默认值并且static
代码块会被执行),为什么static
不会被多次执行?因为有可能两个线程同时检测到类还没被初始化,然后都执行static代码块,结果就把语句1234多打印了,为什么上述情况不会发生。
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Class.forName("StaticClass");//这一行触发类的初始化导致静态代码块执行
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Class.forName("StaticClass");//同样
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
thread2.start();
结果如下:
语句1
语句2
语句3
语句4
有一段英文对其进行了解释:
static initialization block can be triggered from multiple parallel threads (when the loading of the class happens in the first time), Java runtime guarantees that it will be executed only once and in thread-safe manner + when we have more than 1 static block - it guarantees the sequential execution of the blocks, 也就是说,java runtime帮我们做了两件事:
在并行线程中,都出现了第一次初始化类的情况,保证类的初始化只执行一次。
保证
static
代码块的顺序执行
三、单例的另一种写法
有了对static
的知识的了解之后,我们可以写出这样的单例模式:
class Singleton{
private Singleton() {}
private static class NestedClass{
static Singleton instance = new Singleton();//这条赋值语句会在初始化时才运行
}
public static Singleton getInstance() {
return NestedClass.instance;
}
}
懒加载,因为
static
语句会在初始化时才赋值运行,达到了懒加载的效果。锁🔒的效果由
Java runtime
保证,虚拟机帮我们保证static语句在初始化时只会执行一次。
四、总结
如果不知道static
的基础知识和虚拟机类加载的知识,我可能并不会知道这一种方法。理论永远先行于技术,要学好理论才能从根本上提升自己。
来源:https://www.cnblogs.com/--here--gold--you--want/p/15779594.html


猜你喜欢
- C# 日历类的实现代码,具体如下所示:using System;namespace DotNet.Utilities{ ///
- 1:查看是否有存储卡插入String status=Environment.getExternalStorageState();if(sta
- 很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义Vie
- 通过2种方式模拟单个文件上传,效果如下所示开发步骤如下:1、新建一个web工程,导入struts2上传文件所需jar,如下图目录结构2、新建
- 首先在新建了一个web服务文件。public SqlWhhWebService1() &nbs
- 话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerVie
- 数组数组时相同类型数据的有序集合数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成其中,每一个数据称作一个数组元素,每一个数组
- 示例【通过班级查询老师信息】创建t_classes创建t_classessTeacher创建t_teacher创建Classespackag
- 创建一个maven项目导入springboot依赖,注意底 * 释部分<?xml version="1.0&quo
- 安装方式:使用vs自带的nuget管理工具,搜索AutoMapper ,选择第一个安装到你的项目即可。先说说DTODTO是个什么东东?DTO
- 一副扑克有54张牌:大小王+4*13,接下来我们来模拟一下斗地主的发牌过程首先,我们需要买牌,新买来的牌都是按顺序摆放的,因此下一步是洗牌,
-   利用 springboot + redis 实现过滤重复提交的请求,业务流程如下所示,首先定义一个拦
- 前言作为 Android 开发者,想必多多少少要接触启动速度优化相关的事情,当用户越来越多,产品的功能也随着迭代越来越多,App 逐渐变得臃
- 本文实例讲述了连接Wifi和创建Wifi热点的方法。分享给大家供大家参考,具体如下:android的热点功能不可见,用了反射的技术搞定之外。
- C#过滤DataTable中的空数据和重复数据string sql = "select name,age from user&qu
- 1.为什么需要动态内存分配关于这个问题,我们先看看我们之前是如何开辟内存的。int val = 20;//在栈空间上开辟四个字节char a
- 一.类与接口的区别类:描述了一个实体,包括实体的状态,也包括实体可能发出的动作。接口:定义了一个实体可能发出的动作。但是只是定义了这些动作的
- 1. web.xml中配置了CharacterEncodingFilter,配置这个是拦截所有的资源并设置好编号格式。encoding设置成
- 本文实例为大家分享了Java实现多线程在线聊天的具体代码,供大家参考,具体内容如下上一篇博客通过UDP实现了聊天,但只能单方面发送消息,这次
- 背景数据之间两两趋势比较在数据分析应用中是非常常见的应用场景,如下所示:模拟考批次班级学生语文数学英语202302三年一班张小明130145