Java实现单例模式的五种方法介绍
作者:Knight_AL 发布时间:2022-10-20 17:32:56
饿汉式
立即加载
防止new对象,构造私有,写一个公共的方法返回对象
占用空间,线程安全
public class Singleton {
/**
* 私有构造
*/
private Singleton(){
System.out.println("构造函数Singleton");
}
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
}
懒汉式
延迟加载
占用空间小,效率有问题,线程不安全
public class Singleton {
/**
* 私有构造
*/
private Singleton(){
System.out.println("构造函数Singleton");
}
private static Singleton singleton = null;
public static Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
解决线程安全问题
在方法上加synchronized同步锁或是用同步代码块对类加同步锁,此种方式虽然解决了多个实例对象问题,但是该方式运行效率却很低下,下一个线程想要获取对象,就必须等待上一个线程释放锁之后,才可以继续运行。
锁太大
public class Singleton {
/**
* 私有构造
*/
private Singleton(){
System.out.println("构造函数Singleton");
}
private static Singleton singleton = null;
public static synchronized Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
双重检查锁
提高同步锁的效率
使用双重检查锁进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。
第一个if判断
第一个线程进来new了Singleton,那么singleton就有值,第二个线程进来,那么进行第一个if判断,不为null,直接返回,不用再去new了,提升了效率
第二个if判断
两个线程同时进来,在synchronized,第一个线程进入,另一个线程等待,第一个线程new Singleton,然后返回,另一个线程发现了第一个线程走了,进入synchronized,如果不进行if判断,那么还会new Singleton,导致线程不安全
public class Singleton {
/**
* 私有构造
*/
private Singleton(){
System.out.println("构造函数Singleton");
}
private static Singleton singleton = null;
public static synchronized Singleton getInstance(){
if (singleton == null){ //这个检查是提高效率的
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton(); //这个检查是防止线程安全的
}
}
}
return singleton;
}
}
静态内部类
这种方式引入了一个内部静态类(static class),静态内部类只有在调用时才会加载,它保证了Singleton 实例的延迟初始化,又保证了实例的唯一性。它把singleton 的实例化操作放到一个静态内部类中,在第一次调用getInstance() 方法时,JVM才会去加载InnerObject类,同时初始化singleton 实例,所以能让getInstance() 方法线程安全。
特点是:即能延迟加载,也能保证线程安全。
静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。
public class Singleton {
/**
* 私有构造
*/
private Singleton(){
}
private static class InnerObject{
private static Singleton singleton = new Singleton();
}
public static synchronized Singleton getInstance(){
return InnerObject.singleton;
}
}
内部枚举类实现
防止反射和反序列化攻击
实上,通过Java反射机制是能够实例化构造方法为private的类的。这也就是我们现在需要引入的枚举单例模式。
public class SingletonFactory {
/**
* 私有构造
*/
private enum EnumSingleton{
SINGLETON;
private Singleton6 singleton;
//枚举类的构造方法在类加载是被实例化
private EnumSingleton(){
singleton = new Singleton6();
}
public Singleton6 getInstance(){
return singleton;
}
}
public static Singleton6 getInstance(){
return EnumSingleton.SINGLETON.getInstance();
}
}
class Singleton6{
public Singleton6(){
}
}
来源:https://donglin.blog.csdn.net/article/details/128773676


猜你喜欢
- 一、前言最近接到一个任务,需要爬取五级行政区划的所有数据(大概71万条数据在),需要爬取的网站:行政区划 - 行政区划代码查询 发
- 本文实例为大家分享了Java实现宠物商店管理的具体代码,供大家参考,具体内容如下第一种实现方式:抽象类和对象数组public abstrac
- 几乎所有运算符都只能操作“主类型”(Primitives)。例外是“=”、“= =”和“! =”,它们能操作所有对象。除此以外,String
- 前言最近做了一个调查问卷导出的功能,需求是将维护的题目,答案,导出成word,参考了几种方案之后,选择功能强大的freemarker+固定格
- 背景在用了一阵子 Ktor 之后,深感基于协程的方便,但是公司的主要技术栈是 SpringBoot,虽然已经整合了 Kotlin,但是如果有
- 在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取properties
- C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥、锁和原子变量)的方法,我将试图为你介绍这个全新的线
- 题目给定count=0;让5个线程并发累加到1000;思路创建一个类MyRunnable,实现Runnable(继承Thread类也可)定义
- 本文实例讲述了java实现ArrayList根据存储对象排序功能。分享给大家供大家参考,具体如下:与c++中的qsort的实现极为相似,构建
- 目录Bitmap类BitmapData类参考:Bitmap类Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组
- 一、需求:标题可能写的不够全部,下面来看下图片,大家就明白是什么意思了。视频与票的图标跟在标题后面显示,当标题过长时icon显示到省略号…后
- 前言 实际业务开发中,集合的判断和操作也是经常
- Druid动态数据源配置 主要是继承AbstractRoutingDataSource再通过AOP来实现动态数据源切换.下面给大家介绍Dru
- 本文实例讲述了Android中TextView显示插入的图片实现方法。分享给大家供大家参考,具体如下:Android系统默认给TextVie
- 本文实例讲述了Java+Ajax实现的用户名重复检验功能。分享给大家供大家参考,具体如下:今天,我来教大家怎么实现Java+Ajax实现用户
- 一、简介1.1 Log4.net优点几乎所有的大型应用都会有自己的用于跟踪调试的API。因为一旦程序被部署以后,就不太可能再利用专门的调试工
- 模块之间总是存在这一定的接口,从调用方式上看,可以分为三类:同步调用、回调和异步调用。下面着重详解回调机制。1. 概述Java 中的回调机制
- 一开始我就纳闷了,怎么调试都只是一个光溜溜的界面,右侧的工具栏都没有如图:就一个光秃秃的界面,什么都没有,这就对调试很不方便于是我就试了试各
- 现在就为大家介绍一种基于因子分解的RSA算法,这种加密算法有两种实现形式:1、公钥加密,私钥解密;2、私钥加密,公钥解密。下面就为大家分析一
- 在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。但是在通过了Ap