单例模式

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例                  
  1、单例类只能有一个实例。
  2、单例类必须自己自己创建自己的唯一实例。
  3、单例类必须给所有其他对象提供这一实例。

    单例所具备的特点:

  •     私有化的构造函数
  •     私有的静态的全局变量
  •     公有的静态的方法

饿汉式单例:在单例类被加载时候,就实例化一个对象交给自己的引用;

懒汉式单例:在调用取得实例方法的时候才会实例化对象。

饿汉式单例模式

public class Test3 {
	/**
	 * 饿汉式单例模式(线程安全)
	 */
	private static Test3 test3 = new Test3();
	private Test3(){
		
	}
	public static Test3 getInstance(){
		return test3;
	}
}

优点:线程安全。因为它在类加载的时候就初始化了对象

缺点:类加载时初始化。如果程序从头到位都没用使用这个单例的话,单例的对象还是会创建。这就造成了不必要的资源浪费。

懒汉式单例模式

    /**
	 * 懒汉式(线程安全)
	 */
	private static Test3 test3 = null;
	private Test3(){
		
	}
	public synchronized static Test3 getInstance(){
		if(test3 == null) {
			test3 = new Test3();
		}
		return test3;
	}

优点:第一次调用才初始化,避免内存浪费

缺点:加锁,执行效率不高

双层校验锁

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

在获取单例对象的时候,我们先进行了两为空判断,并且在第二次判断前加了锁。

为什么要用两个判空呢?

如果没有第二个判空的,假如第一个线程判断test3 == null,进入拿到锁。再进入第二个判断条件内,创建 一个Test3对象。在这个中途中,另外一个线程进入第一个判断条件内等待锁对象的释放,第一个创建完成之后,第二个就会拿到锁对象,如果没有第二次判空的话,就会再次创建一个对象,这样就不能保证为单例了。

DCL(双层校验锁)模式失效:
test3 = new Test3();这句话执行的时候,会进行下列三个过程:

  1. 分配内存。
  2. 初始化构造函数和成员变量。
  3. 将对象指向分配的空间。

由于JMM(Java Memory Model)的规定,可能会出现1-2-3和1-3-2两种情况。(指令重排序)
所以,就会出现线程A进行到1-3时,就被线程B取走,B发现test3不为null时返回test3 但是此时的test3还没有被初始化成功。所以就出现了错误。这个时候DCL模式就失效了。

由于这个原因我们可以采用Java中的volatile关键字。(volatile——>https://blog.youkuaiyun.com/qq_37937537/article/details/82764667

volatile可以有效防止重排序 ,可以保证代码的有序性。

private static volatile Test3 test3 = null;
	private Test3(){
		
	}
	public static Test3 getInstance(){
		if(test3 == null){
			synchronized (Test3.class) {
				if(test3 == null){
					test3 = new Test3();
				}
			}
		}
		return test3;
	}

静态内部类

       private static class SingletonHolder {  
		    private static final Test3 test3 = new Test3();  
	   }  
	   private Test3 (){}  
	   public static Test1 getInstance() {  
		   return SingletonHolder.test3;  
	   }  

可以发现这种方式,并未加锁,因为第一次加载Test3 类时,并不会实例化单例对象,只有第一次调用getInstance()方法时会导致虚拟机加载SingletonHolder类,这方式不仅能保证对象的单一性,还避免加锁带来的性能问题,又启动了延迟加载的优化。

反射和反序列化方式会破坏单例模式,我们应该怎样解决?

1,这些模式在实现了Serializable接口后,反序列化时单例会被破坏。当从IO流中读取对象时readResolve()方法都会被调用到,实际上就是用readResolve()中返回的对象直接替换在反序列化过程中创建的对象。所以要重写readResolve()方法。

private Object readResolve() throws ObjectStreamException {
        return test3;
    }

2,反射是通过class对象,来调用构造器创建新的对象。那么我们只需要在它调用构造器的时候手动抛出异常即可。

private static Test3 test3 = null;
	private static boolean flag = false;
	private Test3(){
		/**
		 * 反射就是通过它的Class对象来调用构造器创建出新的对象
		 * 我们只需要在构造器中手动抛出异常,导致程序停止就可以达到目的了
		 */
	       if(flag == false)  
             {  
                  flag = !flag;  
              }  
             else 
             {  
                 throw new RuntimeException("单例模式被侵犯!");  
             }  
	}
	public synchronized static Test3 getInstance(){
		if(test3 == null) {
			test3 = new Test3();
		}
		return test3;
	}
}

枚举模式

一个可以直接避免反射,序列化攻击的实现单例模式的方式。

public enum Singleton{
    singleton;
    public void hello(){
        System.out.print("hello");
    }
}

 

内容概要:本文详细介绍了基于滑模控制(SMC)和H∞控制相结合的方法应用于永磁直线同步电机(PMLSM)的鲁棒控制。首先阐述了PMLSM的基本数学模型及其物理意义,包括d-q坐标系下的电压方程和运动方程。随后解释了滑模控制的工作原理,重点在于如何构建滑模面并确保系统沿此面稳定运行。接着讨论了H∞控制的目标——即使在不确定条件下也能保持良好的性能表现。文中还提供了具体的Matlab代码实例,展示了如何利用Matlab控制系统工具箱进行H∞控制器的设计。最后给出了一段完整的Matlab程序框架,演示了两种控制方法的具体实现方式。 适合人群:从事电机控制领域的研究人员和技术人员,尤其是那些想要深入了解滑模控制和H∞控制理论及其在实际工程中应用的人士。 使用场景及目标:适用于需要提高永磁直线同步电机控制系统抗干扰能力和鲁棒性的场合,如工业自动化生产线、精密加工设备等。通过学习本篇文章提供的理论知识和编程技巧,读者能够掌握这两种先进控制策略的应用方法,从而提升自身解决复杂控制问题的能力。 其他说明:文中所涉及的内容不仅限于理论讲解,还包括了大量的实战经验分享,有助于读者快速上手并在实践中不断改进自己的设计方案。同时鼓励读者积极尝试不同的参数配置,以便找到最适合特定应用场景的最佳解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值