Design Pattern 1: Singleton

本文详细介绍了单例模式的实现方式,包括懒汉式、饿汉式、静态内部类及枚举等方式,并探讨了线程安全性和延迟加载的重要性。

概念:单例模式确保某一个类只有一个实例,并且自行实例化向整个系统提供这个实例。
实现要点

  • 构造器声明为private来隐藏,防止其他类调用
  • private static Singleton实例
  • 获取实例方法声明为public来供系统调用

设计单例类的目标

  • 延迟加载-lazy loading
  • 调用效率
  • 线程安全

懒汉

可以达到lazy-loading,线程不安全,实际不会使用

public class Singleton1 {
    private static Singleton1 instance;
    private Singleton1(){}
    public static Singleton1 getInstance(){
        if(instance == null){
            instance = new Singleton1();
        }
        return instance;
    }
}

懒汉,线程安全

Singleton1的线程安全版本,虽然线程安全但是效率太低,实际中也不会使用,因为对象只有在初始化时需要同步,多数情况下并不需要互斥的获得对象,这种加锁方式会造成巨大无意义的资源消耗,Singleton7的双重校验锁方式对此进行了优化。

public class Singleton2 {
    private static Singleton2 instance;
    private Singleton2(){};
    public static synchronized Singleton2 getInstance(){
        if(instance == null){
            instance = new Singleton2();
        }
        return instance;
    }
}

饿汉

没有做到lazy-loading,实际中这种方式会造成资源浪费,因为系统中很多的类的实例都不会用到,加载类时就实例化太浪费!但是这种方式是线程安全的。

public class Singleton3 {
    private static Singleton3 instance = new Singleton3();
    private Singleton3(){}
    public static Singleton3 getInstance(){
        return instance;
    }
}
//另一种方式
public class Singleton4 {
    private static Singleton4 instance = null;
    static {
        instance = new Singleton4();
    }
    private Singleton4(){}
    public static Singleton4 getInstance(){
        return instance;
    }
}

静态内部类

与上种方式的区别是加了个内部类,这样加载类时并不会实例化instance,只有显式的调用getInstance方法的时候才会实例化,巧妙利用了Java虚拟机的类加载机制,既做到了线程安全,有做到了lazy-loading,实际应用中这种方式是比较推荐的。

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

枚举方式

这种方式不仅避免多线程同步问题,还防止反序列化重新创建新的对象

public enum  Singleton6 {
    INSTANCE;
    public void whateverMethod(){}
}

双重校验锁

该方式确保了只有在初始化的时候需要同步,当初始化完成后,再次调用getInstance不会再进入synchronized块。(对Singleton2的改进)但这种方式也被很多人诟病,实际中依然不会采用。
注意这里的instance声明为volatile的必要性
防止指令重排
由于初始化操作 instance=new Singleton()是非原子操作的,主要包含三个过程
1. 给instance分配内存
2. 调用构造函数初始化instance
3. 将instance指向分配的空间(instance指向分配空间后,instance就不为空了)
虽然synchronized块保证了只有一个线程进入同步块,但是在同步块内部JVM出于优化需要可能进行指令重排,例如(1->3->2),instance还没有初始化之前其他线程就会在外部检查到instance不为null,而返回还没有初始化的instance,从而造成逻辑错误。

变量可见性
volatile类型变量可以保证写入对于读取的可见性,JVM不会将volatile变量上的操作与其他内存操作一起重新排序,volatile变量不会被缓存在寄存器,因此保证了检测instance状态时总是检测到instance的最新状态。

public class Singleton7 {
    private volatile static Singleton7 instance;

    private Singleton7() {
    }

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

以上是实现单例的几种方式汇总,其实综上也能发现在实际中能够付诸使用的方式很少,我们这里更多的是从线程安全和lazy-loading的角度更好的理解和实现单例模式。
在Spring使用ThreadLocal解决线程安全问题。我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,为每个线程提供一个独立的变量副本——”以空间换时间”,这样有状态的Bean就可以在多线程中共享了。 在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简便,且拥有更高的并发性。
参考链接
http://www.blogjava.net/kenzhh/archive/2013/03/15/357824.html
http://blog.youkuaiyun.com/neo_ustc/article/details/7913066
http://blog.youkuaiyun.com/jq_ak47/article/details/54894793

提供了基于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、付费专栏及课程。

余额充值