单例模式(懒汉模式-双检锁饿汉模式静态内部类模式)-详细
Posted 栗子~~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式(懒汉模式-双检锁饿汉模式静态内部类模式)-详细相关的知识,希望对你有一定的参考价值。
文章目录
前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
单例模式(懒汉模式-双检锁、饿汉模式、静态内部类模式)-详细
01 单例模式是什么?
单例模式即每一个类都有一个实例
使用场景:线程池、链接池。
02 单例模式的好处?
java 中单例模式带来两个好处:
1.对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级的对象而言,是非常可观的一笔系统开销。
2.由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间。
03 单例模式的三种模式
1、懒汉模式
2、饿汉模式
3、静态内部类
注:推荐使用静态内部类模式使用单例。
03::01 懒汉模式
实现步骤:
1、构造函数私有化–防止外面直接调用;
2、制作一个返回单例方法;
3、实现一个单例类对象 ,并在前面加上volatile;
4、判断-如果该单例对象为空,实例化一个对象(第一次检查);
5、为了防止多线程场景下多个线程同时访问,多次初始化单例类对象,初始化实例对象前加一把锁;
6、为了防止多线程场景下多个线程第一个检查校验过去,走下面的锁竞争后,依次创建实例,违反单例原则, 而在加一次检查的目的是只有为空的时候创建单例对象(第二次检查);
7、!= null 直接返回;
这就是饿汉模式-双检锁。
实例:
class LanSingleton
private volatile static LanSingleton instance;
//
private LanSingleton()
public static LanSingleton getInstance()
if (instance == null)
synchronized (LanSingleton.class)
if (instance == null)
instance = new LanSingleton();
return instance;
测试:
/**
* @description: TODO 懒汉模式-双检锁
* @author 杨镇宇
* @date 2022/2/28 15:08
* @version 1.0
*/
public class LanSingletonTest
public static void main(String[] args)
new Thread(()->
System.out.println(LanSingleton.getInstance());
).start();
new Thread(()->
System.out.println(LanSingleton.getInstance());
).start();
效果:
03::01::01 问:为什么不在方法上加锁,而是在方法内部加锁?
因为直接在方法上加锁,相当于每次线程调用过来都要等上一个线程执行完毕,实际消耗时间太大。
03::01::02 问:单例类对象前面为什么要加volatile 关键字
JVM加载会有重排序的问题,因为CPU为了加载执行速度,会根据自己的优化策略,有些代码会进行优化,即重排序, * 而volatile有防止重排序的特点。
03::02 饿汉模式
特点:立即加载就会使用类,使用类加载机制保障单例模式,因为类加载的时候静态变量就已经加载成功。
实例:
class ESingleton
private static final ESingleton instance = new ESingleton();
private ESingleton()
public static ESingleton getInstance()
return instance;
测试:
/**
* @description: TODO 饿汉模式 立即加载就会使用类,给予类加载机制保障单例模式
* @author 杨镇宇
* @date 2022/2/28 15:40
* @version 1.0
*/
public class ESingletonTest
public static void main(String[] args)
new Thread(()->
System.out.println(ESingleton.getInstance());
).start();
new Thread(()->
System.out.println(ESingleton.getInstance());
).start();
效果:
03::03 静态内部类模式
特点: 静态内部类也是给予类加载机制保证单例模式。
实例:
class ClassSingleton
private static class InnerClassSingletonHolder
private static ClassSingleton instance = new ClassSingleton();
private ClassSingleton()
public static ClassSingleton getInstance()
return InnerClassSingletonHolder.instance;
测试:
/**
* @description: TODO 静态内部类 给予类加载机制保障单例模式
* @author 杨镇宇
* @date 2022/2/28 15:59
* @version 1.0
*/
public class ClassSingletonTest
public static void main(String[] args)
new Thread(()->
System.out.println(ClassSingleton.getInstance());
).start();
new Thread(()->
System.out.println(ClassSingleton.getInstance());
).start();
效果:
03::04 总结
对于静态内部类模式来说,保证线程安全的前提下,有点懒汉模式的味道,即不调用这个getInstance方法时,就不会加载这个类InnerClassSingletonHolder,也就不会浪费空间,而饿汉模式,就会马上加载,会浪费空间,但是它保证单例模式跟饿汉模式一样都是给予JVM的类加载机制保证单例模式,所以有点兼容懒汉模式和饿汉模式的味道,因此使用的话,推荐使用静态内部类模式来写单例模式。
以上是关于单例模式(懒汉模式-双检锁饿汉模式静态内部类模式)-详细的主要内容,如果未能解决你的问题,请参考以下文章
Java 设计模式 -- 单例模式的实现(饿汉式枚举饿汉式懒汉式双检锁懒汉式内部类懒汉式)jdk 中用到单例模式的场景DCL实现单例需用volatile 修饰静态变量
Java 设计模式 -- 单例模式的实现(饿汉式枚举饿汉式懒汉式双检锁懒汉式内部类懒汉式)jdk 中用到单例模式的场景DCL实现单例需用volatile 修饰静态变量