创建型(二) - 单例模式

本文详细介绍了单例设计模式的概念、三种常见实现方式(饿汉、懒汉、双检锁和静态内部类)、优缺点,以及在网站计数器、日志应用等实际场景的应用。

一、概念

单例设计模式(Singleton Design Pattern):一个类只允许创建一个对象(或者实例),那这个类就是一个单例类。

优点:在内存里只有一个实例,减少了内存的开销,避免一个全局使用的类频繁地创建与销毁。

缺点:没有接口,不能继承,与开闭职原则冲突。

使用场景:有些数据在系统中只应该保存一份,就比较适合设计为单例类。比如,系统的配置信息类。除此之外,我们还可以使用单例解决资源访问冲突的问题。

二、实现

1、步骤:

  • 构造方法定义为私有方法。
  • 定义一个私有的类静态实例。
  • 提供一个公有的获取实例的静态方法。

2、实现方式

  • 饿汉模式
public class HungryModeSingleton {
    private static final HungryModeSingleton mInstance = new HungryModeSingleton();

    private HungryModeSingleton() {}
    public static HungryModeSingleton getInstance() {
        return mInstance;
    }
}

总结:在类加载的时候就对实例进行初始化,没有线程安全问题;获取实例的静态方法没有使用同步,调用效率高;但是没有使用懒加载,如果该实例从始至终都没被使用过,则会造成内存浪费。

  • 懒汉模式
public class LazyModeSingleton {
    private static LazyModeSingleton mInstance;

    private LazyModeSingleton () {}
    public static synchronized LazyModeSingleton getInstance() {
        if (mInstance == null){
            mInstance = new LazyModeSingleton();
        }
        return mInstance;
    }
}

总结:上面是线程安全的懒汉模式,在第一次使用的时候才进行初始化,达到了懒加载的效果;但是,这种写法每次获取实例都要进行同步(加锁),因此在频繁获取对象的时候效率较低。

  • 双检锁/双重校验锁(DCL,即 double-checked locking)
 public class DCLModeSingleton {
    private static volatile DCLModeSingleton mInstance;

    private DCLModeSingleton () {}
    public static DCLModeSingleton getInstance() {
        if (mInstance == null){
            synchronized (DCLModeSingleton.class){
               if (mInstance == null){
                   mInstance = new DCLModeSingleton();
              }
           }
       } 
       return mInstance;      
   }
}      

总结:双重校验锁方式在第一次使用的时候才进行初始化,达到了懒加载的效果。并且只有第一次进行初始化才进行同步,因此不会有效率方面的问题。

在上面的例子中,DCLModeSingleton的实例使用了volatile关键字进行修饰,主要是为了解决在一些JDK低版本上有指令重排的问题。
指令重排问题:当线程A执行到9行的时候,线程B执行到6行,CPU在进行对象创建的时候,内部会在保证不影响最终结果的前提下对指令进行重新排序(不影响最终结果只是针对单线程)。例如:
创建对象步骤:分配空间-> 初始化对象 ->设置mInstance指向。
指令重排后:分配空间-> 设置mInstance指向 ->初始化对象
此时线程B执行到第6行,发现mInstance不为空,但是对象并没有初始化完成,会出现问题,但是概率较低。
使用volatile修饰符可以禁止指令重排,防止出现该问题。

  • 静态内部类
public class StaticModeSingleton {
    private StaticModeSingleton () {}

    private static class SingletonHolder{
        private static final StaticModeSingleton INSTANCE = new StaticModeSingleton();
    }
    public static StaticModeSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

总结:SingletonHolder 是一个静态内部类,当外部类StaticModeSingleton被加载的时候,并不会创建 SingletonHolder 实例对象。只有当调用 getInstance() 方法时,SingletonHolder 才会被加载,这个时候才会创建instanceinstance 的唯一性、创建过程的线程安全性,都由 JVM 来保证。所以,这种实现方法既保证了线程安全,又能做到延迟加载。

  • 枚举
public enum Singleton {
    INSTANCE;
    //添加自己需要的操作
    public void doSomeThing() {
    }
}

总结:非懒加载,线程安全,可以避免反序列化重新创建对象。

3、实现方式优缺点对比
设计模式优缺点.PNG

三、应用场景

  • 网站计数器。
  • 应用程序的日志应用。
  • Web项目中的配置对象的读取。
  • 数据库连接池。
  • 多线程池。

单例模式详解

提供了基于BP(Back Propagation)神经网络结合PID(比例-积分-微分)控制策略的Simulink仿真模型。该模型旨在实现对杨艺所著论文《基于S函数的BP神经网络PID控制器及Simulink仿真》中的理论进行实践验证。在Matlab 2016b环境下开发,经过测试,确保能够正常运行,适合学习和研究神经网络在控制系统中的应用。 特点 集成BP神经网络:模型中集成了BP神经网络用于提升PID控制器的性能,使之能更好地适应复杂控制环境。 PID控制优化:利用神经网络的自学习能力,对传统的PID控制算法进行了智能调整,提高控制精度和稳定性。 S函数应用:展示了如何在Simulink中通过S函数嵌入MATLAB代码,实现BP神经网络的定制化逻辑。 兼容性说明:虽然开发于Matlab 2016b,但理论上兼容后续版本,可能会需要调整少量配置以适配不同版本的Matlab。 使用指南 环境要求:确保你的电脑上安装有Matlab 2016b或更高版本。 模型加载: 下载本仓库到本地。 在Matlab中打开.slx文件。 运行仿真: 调整模型参数前,请先熟悉各模块功能和输入输出设置。 运行整个模型,观察控制效果。 参数调整: 用户可以自由调节神经网络的层数、节点数以及PID控制器的参数,探索不同的控制性能。 学习和修改: 通过阅读模型中的注释和查阅相关文献,加深对BP神经网络与PID控制结合的理解。 如需修改S函数内的MATLAB代码,建议有一定的MATLAB编程基础。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值