设计模式-------单例模式

一、模式定义

保证一个类只有一个实例,并且提供一个全局访问点

二、应用场景

重量级的对象,不需要多个实例,如线程池,数据库连接

三、饿汉模式

public class Singleton {
    //类加载的时候instance就已经指向了一个实例
    private static Singleton instance = new Singleton();
    private Singleton(){}

    public static Singleton getInstance(){
        return instance;
    }
}

类加载的 初始化阶段就完成了 实例的初始化 。本质上就是借助于jvm 类加载机制,保证实例的唯一性(初始化过程只会执行一次)及线程安全(JVM以同步的形式来完成类加载的整个过程)
类加载过程:
1.加载:二进制数据到内存中, 生成对应的Class数据结构,
2.连接: a. 验证, b.准备(给类的静态成员变量赋默认值),c.解析
3.初始化: 给类的静态变量赋初值

四、懒汉式模式

public class SingletonDemo2 {
    private static SingletonDemo2 instance = null;

    private SingletonDemo2() {
    }
    //运行时加载对象
    public static SingletonDemo2 getInstance() {
        if (instance == null) {
            instance = new SingletonDemo2();
        }
        return instance;
    }

}

由于该模式是在运行时加载对象的,所以加载类比较快,但是对象的获取速度相对较慢,且线程不安全

五、双层锁模式

public class LazySingleton{
	private volatile static LazySingleton instance;
    private LazySingleton(){}

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

延迟加载, 只有在真正使用的时候,才开始实例化。

volatile:防止指令重排

指令重排
我简单的讲一下,.java文件会被编译成.class文件,比如说我们的.java文件的代码执行顺序为A->B->C>D,但在实实际执行的时候JAVA虚拟机为了性能考虑,编译器和CPU可能会对指令重新排序。我们的代码执行顺序可能就会为A->C->B->D,这就是我理解的指令重排

六、枚举

public class Singleton {
	INSTANCE;
	public void doSomething() {
        System.out.println("doSomething");
    }
}

七、静态内部类

public class SingleTon{
  private SingleTon(){}
 
  private static class SingleTonHoler{
     private static SingleTon INSTANCE = new SingleTon();
 }
 
  public static SingleTon getInstance(){
    return SingleTonHoler.INSTANCE;
  }
}

八、反射攻击

Constructor<LazySingleton> declaredConstructor=LazySingleton.class.getDeclaredConstructor();
declaredConstructor.setAccessible( true );
LazySingleton lazySingleton=declaredConstructor.newInstance();
System.out.println(lazySingleton==LazySingleton.getInstance());

九、序列化攻击

public class serializeSingletonTest {
    public static void main(String[] args) { serializeDestroyMethod();}

    private static void serializeDestroyMethod() {
        HungrySingleton hungrySingleton=null;
        HungrySingleton hungrySingletonNew=null;
        hungrySingleton=HungrySingleton.getInstance();
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(hungrySingleton);

        ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bis);
        hungrySingletonNew= (HungrySingleton) ois.readObject();
        System.out.println(hungrySingleton==hungrySingletonNew);
    }
}

参考文件:
https://zhuanlan.zhihu.com/p/33102022

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值