单例模式饿汉式与懒汉式详解

步骤:
  • 私有构造方法,使得在类的外部不能调用此方法,限制产生多个对象
  • 类初始化时,区分饿汉式与懒汉式的区别
  • 对外部提供调用方法,将创建的对象返回,只能通过类来调用

饿汉式:

  1. 类加载时即创建对象,线程安全
  2. 优点:执行效率高
  3. 缺点:类加载时就初始化,浪费内存资源,懒加载:无
实现:
public class SingletonEH {/*** 饿汉式:*  类加载时即创建对象,线程安全*  优点:执行效率高*  缺点:类加载时就初始化,浪费内存资源,懒加载:无*/private SingletonEH(){};private final static SingletonEH singletonEH = new SingletonEH();public static SingletonEH getInstance() {return singletonEH;}
}
测试:
public static void main(String[] args) {SingletonEH instanceA = SingletonEH.getInstance();SingletonEH instanceB = SingletonEH.getInstance();System.out.println(instanceA == instanceB);
}
饿汉式测试结果:
true
Process finished with exit code 0

懒汉式:

  1. 只有再调用获取实例的时候,才会去初始化实例对象
  2. 懒加载:是
  3. 是否线程安全:否
private SingletonLH(){};
private static SingletonLH singletonLH; // 注意实现方式不同,实例私有化有变化
方式一:最基本的实现方式

不支持多线程,因为没有加锁

实现:
public static SingletonLH getSingletonLH() {if (null == singletonLH) {singletonLH =  new SingletonLH();}return singletonLH;
}
方式二:静态内部类

也即饿汉式和懒汉式的组合,调用 getInstance() 方法时才创建,达到了类似懒汉式的效果,同时又是线程安全的

实现:
private static class Holder{private static SingletonLH singletonStatic = new SingletonLH();
}public static SingletonLH getInstanceLHStatic() {return Holder.singletonStatic;
}
方式三:加锁

synchronized

实现:
public static synchronized SingletonLH getInstanceSy() {if (null == singletonLH) {singletonLH =  new SingletonLH();}return singletonLH;
}
方式四:双重锁校验

通常线程安全,加volatile的作用是禁止指令重排。(由于 JVM 底层内部模型原因,偶尔会出问题。不建议使用)

private volatile static SingletonLH singletonLHVolatile;public static SingletonLH getSingletonLHVolatile() {if (null == singletonLHVolatile) {synchronized (SingletonLH.class) {if (null == singletonLHVolatile) {singletonLHVolatile = new SingletonLH();}}}return singletonLHVolatile;
}
方式五:ThreadLocal方式

线程安全,ThreadLocal采用以空间换时间的方式,为每一个线程都提供一份变量,因此可以同时访问而互不影响。

实现:
private static final ThreadLocal<SingletonLH> singletonThreadLocal = new ThreadLocal<SingletonLH>(){@Overrideprotected SingletonLH initialValue() {return new SingletonLH();}
};public static SingletonLH getInstanceThreadLocal() {return singletonThreadLocal.get();
}
方式六:CAS 锁方式

CAS锁(Compare and Swap):比较并交换,是一种有名的无锁算法,属于乐观锁)。用CAS锁来实现单例模式是线程安全的

实现:
private static final AtomicReference<SingletonLH> instanceCAS = new AtomicReference<SingletonLH>();public static final SingletonLH getInstanceCAS() {for (; ; ) {SingletonLH instance = instanceCAS.get();if (null != instance) {return instance;}instance = new SingletonLH();if (instanceCAS.compareAndSet(null, instance)) {return instance;}}
}

​ 懒汉式还有一种实现方式就可以使用枚举,枚举实现的单例,代码简洁清晰。并且它还自动支持序列化机制,绝对防止多次实例化。这个大家自己可以动手实现下,代码就不粘贴出来了。

测试:
public static void main(String[] args) {SingletonLH instanceLHA = SingletonLH.getSingletonLH();SingletonLH instanceLHB = SingletonLH.getSingletonLH();System.out.println("基本懒汉式:" + (instanceLHA == instanceLHB));SingletonLH instanceLHStaticA = SingletonLH.getInstanceLHStatic();SingletonLH instanceLHStaticB = SingletonLH.getInstanceLHStatic();System.out.println("静态代码块式:" + (instanceLHStaticA == instanceLHStaticB));SingletonLH instanceSyA = SingletonLH.getInstanceSy();SingletonLH instanceSyB = SingletonLH.getInstanceSy();System.out.println("加锁式:" + (instanceSyA == instanceSyB));SingletonLH instanceLHVolatileA = SingletonLH.getSingletonLHVolatile();SingletonLH instanceLHVolatileB = SingletonLH.getSingletonLHVolatile();System.out.println("双重锁:" + (instanceLHVolatileA == instanceLHVolatileB));SingletonLH instanceThreadLocalA = SingletonLH.getInstanceThreadLocal();SingletonLH instanceThreadLocalB = SingletonLH.getInstanceThreadLocal();System.out.println("ThreadLocal方式:" + (instanceThreadLocalA == instanceThreadLocalB));SingletonLH instanceCASA = SingletonLH.getInstanceCAS();SingletonLH instanceCASB = SingletonLH.getInstanceCAS();System.out.println("CAS方式:" + (instanceCASA == instanceCASB));
}
懒汉式不同方式下的测试结果
基本懒汉式:true
静态代码块式:true
加锁式:true
双重锁:true
ThreadLocal方式:true
CAS方式:trueProcess finished with exit code 0

单例模式饿汉式与懒汉式详解相关推荐

  1. Singleton模式(单例模式) 饿汉式和懒汉式

    目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例. 好比一个国家就只有一个皇帝(XXX),此时每个人叫的"皇帝"都是指叫的XXX本人; 常见单例模式类型: ...

  2. 单例模式——饿汉式和懒汉式

    单例模式:一个类只允许存在唯一的对象,并提供它的访问方式 创建思路: 1.禁止在类的外部创建对象:私有化构造函数 2.在类的内部提供唯一的对象:静态成员变量 3.提供访问唯一对象的方法:静态成员函数 ...

  3. Java-Day12 面向对象的三大特征之封装、继承,单例模式(饿汉式、懒汉式)、方法重写 (覆盖)、注解 (annotation)、super关键字、对象的创建流程超详细

    目录 1. 面向对象的三大特征之封装 1.1 封装的含义 1.2 封装的目的 1.3 封装的优点 1.4 封装的实现过程 1.5 拓展知识:JavaBean 2. 面向对象的三大特征之继承 2.1 继 ...

  4. Java中单例模式—饿汉式和懒汉式

    所谓单例模式就是为了确保类在内存中只有一个对象,之所以会出现单例模式是因为,单例模式在系统内存中只存在一个对象,可以节约资源 目录 一.饿汉式 二.懒汉式 一.饿汉式 该方式在开发中是经常用的,因为这 ...

  5. 【学习笔记】【C++整理A】【总】单例模式-饿汉式、懒汉式;

    文章目录 一.语言分类: 三.基础A:- 函数重载.默认参数.extern "C".重复包含 1.函数重载 2.默认参数 3.extern "C" 4.防止重复 ...

  6. 单例模式之饿汉式与懒汉式

    常见的单例模式 本文仅讲解单例模式中的饿汉式和懒汉式(双检索) 文章目录 常见的单例模式 前言 一.单例模式的优缺点 二.详解懒汉式.饿汉式 1.饿汉式 2.懒汉式(双检锁) 总结 前言 先来简单的说 ...

  7. 单例模式(饿汉式和懒汉式)

    以前学习单例的时候,只理解了简单部分.这次看DRP,对单例的饿汉式和懒汉式有了一些认识和对比. 在实际的开发中,有些地方需要一个类只有一个实例.比如:网站在线人数的计数器,再比如IDE中的工具箱之类的 ...

  8. Java实现单例模式之饿汉式、懒汉式、枚举式,带测试。

    Java实现单例的3种普遍的模式,饿汉式.懒汉式.枚举式. 具体代码如下: package com.lcx.mode;/*** * 饿汉式单例,不管以后用不用这个对象,我们一开始就创建这个对象的实例, ...

  9. 单例模式饿汉式/懒汉式的区别

    単例设计模式(Singleton Pattern): 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法. 如果我们要 ...

最新文章

  1. LeetCode简单题之三维形体的表面积
  2. 标签传播算法_复杂网络社区发现算法汇总
  3. python学精通要多久-学习Python零基础需要学多久?
  4. Hadoop源码导入Eclipse
  5. 也谈表达式分析和计算
  6. C盘突然爆满怎么办?
  7. hdu 5521 Meeting(最短路)
  8. 设计模式—工厂模式之简单工厂模式
  9. 欢迎使用CSDN-markdown编辑器啦啦啦啦啦
  10. redis核心与实战(一)数据结构篇
  11. JAVA 简单的抽奖程序
  12. java 模板方法_Java设计模式21:模板方法(Template Method)
  13. 基于特征融合的图像情感识别
  14. Mybatis中DAO层接口没有写实现类,Mapper中的方法和DAO接口方法是怎么绑定到一起的...
  15. Form 表单提交参数
  16. 求推荐民法论文选题?
  17. php win8 下载64位下载,万能驱动助理(e驱动) Win8.1 64位专版 6.6 官方版
  18. 使用python获取nature系列期刊封面高清图片
  19. word参考文献插入和上标设置
  20. 关于黑莓手机 三键重启的操作方法

热门文章

  1. 机器人也会搞文艺?YuMi刷新了你的眼球,当上了乐队指挥
  2. 产品设计之需求的等级
  3. 装修就选集成墙板装饰材料
  4. 程序员,练就哪些技能才胜任架构师?
  5. 个人成长的 15 种能力
  6. 最小攻击超过最大攻击_比武招亲最小攻击和最大攻击的优劣势分析
  7. ubuntu服务器完全卸载nginx服务器
  8. 冬令营第一天(1.18)
  9. Build generate signed apk 时忘记打包签名密码怎么办?这里有方法来帮你找回
  10. MATLAB安装Robotic Toolbox机器人工具箱