单例模式的使用总结

单例模式的使用总结目录一、单例模式的定义和应用场景(一)定义及基本要点(二)应用场景二、饿汉式单例模式(一)基本代码展示分析(二)基本分析和建议三、懒汉式单例模式(双重检查锁)(一)基本代码展示分析(二)基本分析和建议四、静态内部类实现单例模式(一)基本代码展示分析(二)基本分析和建议五、注册式单例模式(一)枚举式单例模式代码及分析:(EffectiveJa…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

目录

一、单例模式的定义和应用场景

(一)定义及基本要点

(二)应用场景

二、饿汉式单例模式

(一)基本代码展示分析

(二)基本分析和建议

三、懒汉式单例模式(双重检查锁)

(一)基本代码展示分析

(二)基本分析和建议

四、静态内部类实现单例模式

(一)基本代码展示分析

(二)基本分析和建议

五、注册式单例模式

(一)枚举式单例模式代码及分析:(Effective Java推荐单例模式)

(二)容器式单例模式代码及分析:(适用于实例非常多的情况,便于管理,但是是非线程安全的)

参考书籍、文献和资料


一、单例模式的定义和应用场景

(一)定义及基本要点

单例模式是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。

该模式有三个基本要点

  • 一是这个类只能有一个实例;
  • 二是它必须自行创建这个实例;
  • 三是它必须自行向整个系统提供这个实例。

(二)应用场景

应用场景:J2EE中的ServlertContext、SerletContextConfig等、Spring框架应用中的ApplicationContext、数据库连接池等。

二、饿汉式单例模式

(一)基本代码展示分析

/**
 * 描述:饿汉式单例模式
 * 优点:没有任何锁,执行效率高,用户体验比懒汉式单例模式更好
 * 缺点:类加载的时候就初始化,不管用不用都占内存空间
 * 建议:适用于单例模式较少的场景
 *      如果我们在程序启动后,一定会加载到类,那么用饿汉模式实现的单例简单又实用;
 *      如果我们是写一些工具类,则优先考虑使用懒汉模式,可以避免提前被加载到内存中,占用系统资源。
 *
 * @author yanfengzhang
 * @date 2020-01-02 20:39
 */
public class HungrySingleton {
    private final static HungrySingleton HUNGRY_SINGLETON = new HungrySingleton();

    private HungrySingleton() {
    }

    public static HungrySingleton getInstance() {
        return HUNGRY_SINGLETON;
    }
}

(二)基本分析和建议

优点:没有任何锁,执行效率高,用户体验比懒汉式单例模式更好
缺点:类加载的时候就初始化,不管用不用都占内存空间
建议:

  • 适用于单例模式较少的场景
  • 如果我们在程序启动后,一定会加载到类,那么用饿汉模式实现的单例简单又实用;
  • 如果我们是写一些工具类,则优先考虑使用懒汉模式,可以避免提前被加载到内存中,占用系统资源。

三、懒汉式单例模式(双重检查锁)

(一)基本代码展示分析

/**
 * 描述:懒汉式单例模式---双重检查锁
 * 相比单锁而言,双重检查锁性能上虽然有提升,但是依旧用到了synchronized关键字总归要上锁,对程序性能还是存在一定的性能影响
 * 不算最优--存在优化空间
 *
 * 建议:如果我们在程序启动后,一定会加载到类,那么用饿汉模式实现的单例简单又实用;
 *      如果我们是写一些工具类,则优先考虑使用懒汉模式,可以避免提前被加载到内存中,占用系统资源。
 *
 * @author yanfengzhang
 * @date 2020-01-02 20:53
 */
public class LazyDoubleCheckSingleton {
    /**
     * volatile 关键字可以保证线程间变量的可见性,还有一个作用就是阻止局部重排序的发生
     */
    private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;

    private LazyDoubleCheckSingleton() {
    }

    public static LazyDoubleCheckSingleton getInstance() {
        if (null == lazyDoubleCheckSingleton) {
            synchronized (LazyDoubleCheckSingleton.class) {
                if (null == lazyDoubleCheckSingleton) {
                    lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
                }
            }
        }
        return lazyDoubleCheckSingleton;
    }
}

(二)基本分析和建议

相比单锁而言,双重检查锁性能上虽然有提升,但是依旧用到了synchronized关键字总归要上锁,对程序性能还是存在一定的性能影响。注意里面volatile的使用!!!

建议:

  • 如果我们在程序启动后,一定会加载到类,那么用饿汉模式实现的单例简单又实用;
  • 如果我们是写一些工具类,则优先考虑使用懒汉模式,可以避免提前被加载到内存中,占用系统资源。

四、静态内部类实现单例模式

(一)基本代码展示分析

/**
 * 描述:屏蔽饿汉式单例模式的内存浪费问题和双重检查锁中synchronized的性能问题
 * 避免因为反射破坏单例
 *
 * @author yanfengzhang
 * @date 2020-01-02 21:08
 */
public class LazyInnerClassSingleton {
    /**
     * 使用LazyInnerClassSingleton的时候会先默认初始化换内部类
     * 如果没有使用,则内部类是不加载的
     */
    private LazyInnerClassSingleton() {
        /*为了避免反射破坏单例,需要在构造方法中增加限制,一旦出现多次重复创建,直接抛出异常*/
        if (null != Lazyholder.LAZY_INNER_CLASS_SINGLETON) {
            throw new RuntimeException("创建LazyInnerClassSingleton异常,不允许创建多个实例!");
        }
    }

    /**
     * 每一个关键字都不是多余的,static是为了使单例的空间共享,保证这个方法不会被重写、重载
     */
    public static final LazyInnerClassSingleton getInstance() {
        /*在返回结果前,一定会先加载内部类*/
        return Lazyholder.LAZY_INNER_CLASS_SINGLETON;
    }

    /**
     * 默认不加载
     */
    private static class Lazyholder {
        private static final LazyInnerClassSingleton LAZY_INNER_CLASS_SINGLETON = new LazyInnerClassSingleton();
    }
}

(二)基本分析和建议

屏蔽饿汉式单例模式的内存浪费问题和双重检查锁中synchronized的性能问题,同时考虑避免因为反射破坏单例问题。

相对而言性能最好!

五、注册式单例模式

注册式单例模式/登记式单例模式,将每个实例都登记到一个地方,使用唯一的标识获取单例。

注册单例模式有两种:枚举式单例模式+容器式单例模式

(一)枚举式单例模式代码及分析:(Effective Java推荐单例模式)

/**
 * 描述:注册式单例模式/登记式单例模式,将每个实例都登记到一个地方,使用唯一的标识获取单例。
 * 注册单例模式有两种:枚举式单例模式+容器式单例模式
 * 此为枚举式单例模式---Effective Java推荐单例模式
 *
 * @author yanfengzhang
 * @date 2020-01-03 09:59
 */
public enum EnumSingleton {
    /*枚举式单例模式*/
    INSTANCE;

    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}

(二)容器式单例模式代码及分析:(适用于实例非常多的情况,便于管理,但是是非线程安全的)

/**
 * 描述:注册式单例模式/登记式单例模式,将每个实例都登记到一个地方,使用唯一的标识获取单例。
 * 注册单例模式有两种:枚举式单例模式+容器式单例模式
 * 建议:容器式单例模式适用于实例非常多的情况,便于管理,但是是非线程安全的。
 *
 * @author yanfengzhang
 * @date 2020-01-03 10:51
 */
public class ContainerSingleton {
    private ContainerSingleton() {
    }

    private static Map<String, Object> ioc = new ConcurrentHashMap<>();

    public static Object getBean(String className) {
        synchronized (ioc) {
            if (ioc.containsKey(className)) {
                return ioc.get(className);
            }
            Object obj = null;
            try {
                obj = Class.forName(className).newInstance();
                ioc.put(className, obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return obj;
        }
    }
}

 

参考书籍、文献和资料

1.《Sring 5 核心原理与30个类手写实战》,谭勇徳,中国公信出版社,2019.

2.极客时间课程《Java性能调优实战》,刘超,2019.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/160003.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【模式识别】多层感知器 MLP[通俗易懂]

    【模式识别】多层感知器 MLP[通俗易懂]由前面介绍看到,单个感知器能够完成线性可分数据的分类问题,是一种最简单的可以“学习”的机器。但他无法解决非线性问题。比如下图中的XOR问题:即(1,1)(-1,-1)属于同一类,而(1,-1)(-1,1)属于第二类的问题,不能由单个感知器正确分类。即在Minsky和Papert的专著《感知器》所分析的:感知器只能解决所谓一阶谓词逻辑问题:与(AND),或(OR)等,而不能解决异或(XOR)…

    2022年6月18日
    29
  • delay函数的用法及声明

    delay函数的用法及声明在VC中使用带上头文件#include注意:在VC中Sleep中的第一个英文字符为大写的”S”在标准C中是sleep,不要大写..下面使用大写的来说明,,具体用什么看你用什么编译器.简单的说VC用Sleep,别的一律使用sleep.Sleep函数的一般形式:Sleep(unisgnedlong);其中,Sleep()里面的单位,是以毫秒为单位

    2022年6月2日
    60
  • python抢淘宝的东西-Python 实现毫秒级淘宝抢购脚本的示例代码

    python抢淘宝的东西-Python 实现毫秒级淘宝抢购脚本的示例代码本篇文章主要介绍了Python通过selenium实现毫秒级自动抢购的示例代码,通过扫码登录即可自动完成一系列操作,抢购时间精确至毫秒,可抢加购物车等待时间结算的,也可以抢聚划算的商品。博主不提供任何服务器端程序,也不提供任何收费抢购软件。该文章仅作为学习selenium框架的一个示例代码。该思路可运用到其他任何网站,京东,天猫,淘宝均可使用,且不属于外挂或者软件之类,只属于一个自动化点击工具,…

    2022年6月10日
    42
  • SQL Where 字符串拼接「建议收藏」

    SQL Where 字符串拼接「建议收藏」declare@svarchar(100)set@s=’1,2,3′–法一:select*fromtbwherecharindex(‘,’+ltrim(id)+’,’,’,’+@s+’,’)>0–法二:exec(‘select*fromtbwhereidin(‘+@s+’)’)转载于:https://www.cnblo…

    2022年6月20日
    92
  • 开源 MQTT 服务器

    开源 MQTT 服务器到目前为止,比较流行的开源MQTT服务器有几个:1.EclipseMosquitto使用C语言实现的MQTT服务器。Eclipse组织还还包含了大量的MQTT客户端项目:https://www.eclipse.org/paho/#2.EMQX使用Erlang语言开发的MQTT服务器,内置强大的规则引擎,支持许多其他IoT协议比如MQTT-SN、CoAP、LwM2M等。3.Mosca使用Node.JS开发的MQTT服务器,简单易用

    2022年5月8日
    48
  • pycharm版本区别_怎么看pycharm的python版本

    pycharm版本区别_怎么看pycharm的python版本1、分类:专业版是收费的Professional教育版是免费eduhttps://www.jetbrains.com/pycharm-edu/whatsnew/社区版是免费的FreeCommunity2、教育版是教学式的,更适合学生。老师可以用他创建教学,学生可以通过他完成教学作业。集成了一个python的课程学习平台,可以有题目或者新手指导学习。需要足够的英语来支…

    2022年8月27日
    9

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号