单例模式饿汉式与懒汉式详解
单例模式饿汉式与懒汉式详解
步骤:
- 私有构造方法,使得在类的外部不能调用此方法,限制产生多个对象
- 类初始化时,区分饿汉式与懒汉式的区别
- 对外部提供调用方法,将创建的对象返回,只能通过类来调用
饿汉式:
- 类加载时即创建对象,线程安全
- 优点:执行效率高
- 缺点:类加载时就初始化,浪费内存资源,懒加载:无
实现:
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
懒汉式:
- 只有再调用获取实例的时候,才会去初始化实例对象
- 懒加载:是
- 是否线程安全:否
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
单例模式饿汉式与懒汉式详解相关推荐
- Singleton模式(单例模式) 饿汉式和懒汉式
目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例. 好比一个国家就只有一个皇帝(XXX),此时每个人叫的"皇帝"都是指叫的XXX本人; 常见单例模式类型: ...
- 单例模式——饿汉式和懒汉式
单例模式:一个类只允许存在唯一的对象,并提供它的访问方式 创建思路: 1.禁止在类的外部创建对象:私有化构造函数 2.在类的内部提供唯一的对象:静态成员变量 3.提供访问唯一对象的方法:静态成员函数 ...
- Java-Day12 面向对象的三大特征之封装、继承,单例模式(饿汉式、懒汉式)、方法重写 (覆盖)、注解 (annotation)、super关键字、对象的创建流程超详细
目录 1. 面向对象的三大特征之封装 1.1 封装的含义 1.2 封装的目的 1.3 封装的优点 1.4 封装的实现过程 1.5 拓展知识:JavaBean 2. 面向对象的三大特征之继承 2.1 继 ...
- Java中单例模式—饿汉式和懒汉式
所谓单例模式就是为了确保类在内存中只有一个对象,之所以会出现单例模式是因为,单例模式在系统内存中只存在一个对象,可以节约资源 目录 一.饿汉式 二.懒汉式 一.饿汉式 该方式在开发中是经常用的,因为这 ...
- 【学习笔记】【C++整理A】【总】单例模式-饿汉式、懒汉式;
文章目录 一.语言分类: 三.基础A:- 函数重载.默认参数.extern "C".重复包含 1.函数重载 2.默认参数 3.extern "C" 4.防止重复 ...
- 单例模式之饿汉式与懒汉式
常见的单例模式 本文仅讲解单例模式中的饿汉式和懒汉式(双检索) 文章目录 常见的单例模式 前言 一.单例模式的优缺点 二.详解懒汉式.饿汉式 1.饿汉式 2.懒汉式(双检锁) 总结 前言 先来简单的说 ...
- 单例模式(饿汉式和懒汉式)
以前学习单例的时候,只理解了简单部分.这次看DRP,对单例的饿汉式和懒汉式有了一些认识和对比. 在实际的开发中,有些地方需要一个类只有一个实例.比如:网站在线人数的计数器,再比如IDE中的工具箱之类的 ...
- Java实现单例模式之饿汉式、懒汉式、枚举式,带测试。
Java实现单例的3种普遍的模式,饿汉式.懒汉式.枚举式. 具体代码如下: package com.lcx.mode;/*** * 饿汉式单例,不管以后用不用这个对象,我们一开始就创建这个对象的实例, ...
- 单例模式饿汉式/懒汉式的区别
単例设计模式(Singleton Pattern): 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法. 如果我们要 ...
最新文章
- LeetCode简单题之三维形体的表面积
- 标签传播算法_复杂网络社区发现算法汇总
- python学精通要多久-学习Python零基础需要学多久?
- Hadoop源码导入Eclipse
- 也谈表达式分析和计算
- C盘突然爆满怎么办?
- hdu 5521 Meeting(最短路)
- 设计模式—工厂模式之简单工厂模式
- 欢迎使用CSDN-markdown编辑器啦啦啦啦啦
- redis核心与实战(一)数据结构篇
- JAVA 简单的抽奖程序
- java 模板方法_Java设计模式21:模板方法(Template Method)
- 基于特征融合的图像情感识别
- Mybatis中DAO层接口没有写实现类,Mapper中的方法和DAO接口方法是怎么绑定到一起的...
- Form 表单提交参数
- 求推荐民法论文选题?
- php win8 下载64位下载,万能驱动助理(e驱动) Win8.1 64位专版 6.6 官方版
- 使用python获取nature系列期刊封面高清图片
- word参考文献插入和上标设置
- 关于黑莓手机 三键重启的操作方法