设计模式系列—单例设计模式
文章插图
本文作者:何建辉(公众号:org_yijiaoqian)
前言
- 23种设计模式速记
文章插图
模式定义保证一个类只有一个实例 , 并且提供一个全局访问点 。
场景说明重量级的对象 , 不需要多个实例 , 如线程池 , 数据库连接池 。
文章插图
单例模式有八种
- 饿汉式(静态常量)
- 饿汉式(静态代码块)
- 懒汉式(线程不安全)
- 懒汉式(线程安全 , 同步方法)
- 懒汉式(线程安全 , 同步代码块)
- 双重检查(DCL)
- 静态内部类
- 枚举
- 构造器私有化(防止 new)
- 类的内部创建对象
- 只向外部暴露一个静态的公共方法(getInstance)
package com.niuh.designpattern.singleton.v1;/** *饿汉模式(静态变量) *类加载到内存后 , 就实例化一个单例 。 JVM保证线程安全 *简单使用 , 推荐使用 *唯一缺点:不管用到与否 , 类装载时就完成实例化 *Class.forName("") *(话说你不用的 , 你装载它干啥) */public class Singleton {// 1. 构造器私有化(防止new)private Singleton () {}// 2. 本类内部创建对象private final static Singleton instance = new Singleton();// 3. 提供一个公有的静态方法 , 返回实例对象 , 提供给外部使用public static Singleton getInstance() {return instance;}}class SingletonTest01 {public static void main(String[] args) {// 测试Singleton instance1 = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();System.out.println(instance1 == instance2); // trueSystem.out.println("instance1.hashCode=" + instance1.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}
优缺点- 优点:写法简单 , 实际上在类装载的时候就完成类实例化 , 避免类线程同步问题 。
- 缺点:在类装载的时候就完成了实例化 , 没有实现 Lazy Loading 懒加载 的效果 。 如果从始至终就没有使用过这个实例 , 会造成内存的浪费 。
因此:这种单例模式可用 , 但是可能会造成内存的浪费 。 除非开发人员能肯定 , 此类一定会被用到 , 那么内存就不会被浪费 。
饿汉式(静态代码块)代码示例
/** * 饿汉式(静态代码块) */public class Singleton {// 1. 构造器私有化private Singleton() {}// 2. 本类内部创建对象实例private static Singleton instance;// 在静态代码块中 , 创建单例对象static {instance = new Singleton();}// 3. 提供一个公有的静态方法 , 返回实例对象public static Singleton getInstance() {return instance;}}
优缺点和上面一种很类似 , 都是在类内部实例化 , 只不过类的实例化放在了静态代码块中 。 类一加载 , 就执行类静态代码块中的代码 。 优缺点和上面一样 。这种单例模式可用 , 但是如果不用 , 可能会造成内存的浪费 。
懒汉式(线程不安全)代码示例
package com.niuh.designpattern.singleton.v3;/** * * 懒汉式(线程不安全) */public class Singleton {private static Singleton instance;// 构造函数私有化private Singleton() {}// 提供一个静态的公共方法 , 当使用到该方法时 , 才创建 instance , 即懒汉式public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}class SingletonTest02 {public static void main(String[] args) {// 测试for (int i = 0; i< 100; i++) {new Thread(() ->System.out.println(Singleton.getInstance().hashCode())).start();}}}
优缺点- 起到了 懒加载 的效果 , 但是只能在 单线程下使用;
- 如果在多线程下 , 一个线程进入了 if(instance == null) 判断语句块 , 可能另外一个线程也通过了这个语句判断 , 这是会产生多个实例 , 所以在多线程环境下不可使用这种方式 。
懒汉式(线程安全 , 同步方法)代码示例
- 看不上|为什么还有用户看不上华为Mate40系列来看看内行人怎么说
- 采用|消息称一加9系列将推出三款新机,新增一加9E
- 世代|Z星球——腾讯布局Z世代教育社交的新尝试
- 脉搏|把握时代发展脉搏,尽展巴蜀版权风采——2020年成都数字版权交易博览会成功举办
- 系列|首销300000台!红米Note 9系列,或许可以说恭喜你了?
- 系列|联想碰瓷Redmi后正式复活乐檬手机!乐檬K12系列即将到来
- 系列|Redmi Note9系列三剑客来袭,差别到底有多大?该如何选择?
- 超强|RedmiNote9系列发布!天玑800U赋予超强5G性能
- 回顾|华为P系列回顾
- 情况|刚发布就卖出30万台:红米Note9系列稳了,销售情况追赶前代