Java单例模式的几种常见写法
作者:??Java中文社群???? 时间:2023-10-23 18:27:45
1.饿汉模式
饿汉模式也叫预加载模式,它是在类加载时直接创建并初始化单例对象,所以它并不存在线程安全的问题。它是依靠 ClassLoader 类机制,在程序启动时只加载一次,因此不存在线程安全问题,它的实现代码如下:
public class Singleton {
// 1.防止外部直接 new 对象破坏单例模式
private Singleton() {}
// 2.通过私有变量保存单例对象
private static Singleton instance = new Singleton();
// 3.提供公共获取单例对象的方法
public static Singleton getInstance() {
return instance;
}
}
优点:实现简单、不存在线程安全问题。 缺点:类加载时就创建了对象,创建之后如果没被使用,就造成了资源浪费的情况。
2.懒汉模式
懒汉模式和饿汉模式正好是相反的,所谓的懒汉模式也就是懒加载(延迟加载),指的是它只有在第一次被使用时,才会被初始化,
它的实现代码如下:
public class Singleton {
// 1.防止外部直接 new 对象破坏单例模式
private Singleton() {}
// 2.通过私有变量保存单例对象
private static volatile Singleton instance = null;
// 3.提供公共获取单例对象的方法
public static Singleton getInstance() {
if (instance == null) { // 第一次效验
synchronized (Singleton.class) {
if (instance == null) { // 第二次效验
instance = new Singleton();
}
}
}
return instance;
}
}
懒汉模式使用的是双重效验锁和 volatile 来保证线程安全的,从上述代码可以看出,无论是饿汉模式还是懒汉模式,它们的实现步骤都是一样的:
创建一个私有的构造方法,防止其他调用的地方直接 new 对象,这样创建出来的对象就不是单例对象了。
创建一个私有变量来保存单例对象。
提供一个公共的方法返回单例对象。
懒汉模式相比于饿汉模式来说,不会造成资源的浪费,但写法要复杂一些。
3.静态内部类
静态内部类既能保证线程安全,又能保证懒加载,它只有在被调用时,才会通过 ClassLoader 机制来加载和初始化内部静态类,因此它是线程安全的,此模式的实现代码如下:
public class Singleton {
// 1.防止外部直接 new 对象破坏单例模式
private Singleton() {
}
// 2.静态内部类
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
// 3.提供公共获取单例对象的方法
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
4.枚举
枚举也是在第一次被使用时,才会被 Java 虚拟机加载并初始化,所以它也是线程安全的,且是懒加载的,它的实现代码如下:
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
来源:https://juejin.cn/post/7101845775516172295
标签:Java,单例,模式
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
C#基于WinForm实现串口通讯
2023-12-26 02:03:39
![](https://img.aspxhome.com/file/2023/1/113751_0s.jpg)
解决springboot生成bean名称冲突(AnnotationBeanNameGenerator)
2023-01-09 22:27:11
![](https://img.aspxhome.com/file/2023/0/125240_0s.png)
MaterialApp Flutter 应用全局配置与主题管理详解
2023-05-03 18:50:48
Spring Boot+Mybatis的整合过程
2023-12-20 06:50:18
![](https://img.aspxhome.com/file/2023/7/84317_0s.png)
Java 基础语法
2021-09-21 19:26:32
C# 基础入门--常量
2022-01-29 18:54:53
![](https://img.aspxhome.com/file/2023/0/106530_0s.png)
C#多线程处理多个队列数据的方法
2021-12-26 19:31:02
java计算给定字符串中出现次数最多的字母和该字母出现次数的方法
2022-01-13 03:00:04
MyBatis图文并茂讲解注解开发多对多查询
2022-10-27 17:05:04
![](https://img.aspxhome.com/file/2023/1/67991_0s.png)
Java OkHttp框架源码深入解析
2023-11-29 03:22:50
C# 静态构造函数使用总结
2022-04-28 16:27:35
![](https://img.aspxhome.com/file/2023/5/129635_0s.jpg)
关于mybatis使用${}时sql注入的问题
2023-04-18 03:29:40
![](https://img.aspxhome.com/file/2023/3/66683_0s.png)
SpringBoot整合Spring Data Elasticsearch的过程详解
2023-01-25 22:39:41
![](https://img.aspxhome.com/file/2023/7/80277_0s.png)
Flutter Future异步操作详细讲解
2022-04-05 17:55:32
在C#中global关键字的作用及其用法
2021-12-24 04:33:19
详解Android Activity之间跳转出现短暂黑屏的处理方法
2021-06-28 04:44:03
Android实现流动的渐变色边框效果
2023-06-28 08:24:13
![](https://img.aspxhome.com/file/2023/9/117129_0s.png)
详解C#中的依赖注入和IoC容器
2023-03-11 09:05:19
![](https://img.aspxhome.com/file/2023/2/82232_0s.png)
基于Spring@Autowired注解与自动装配详谈
2022-01-14 09:38:49
C#前端验证和后台验证代码实例
2023-09-17 00:21:29
![](https://img.aspxhome.com/file/2023/6/114066_0s.png)