1.创建型-单例模式

  • 饿汉式、懒汉式区别
    1.饿汉式:在程序启动或单件模式类被加载的时候,单件模式实例就已经被创建。
    2.懒汉式:当程序第一次访问单件模式实例时才进行创建。
    3.懒汉式时间换空间,节约内存空间;饿汉式空间换时间,节省运行时间
    4.饿汉式是线程安全的,懒汉式是存在线程安全问题

  • 饿汉式为什么是线程安全的
    因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的;而懒汉式在创建对象的时候在多线程环境下,其它线程有可能已经创建了对象,存在线程安全问题

  • 线程单例、进程单例、集群单例
    单例模式是进程程单一;ThreadLocal 可以实现线程单一;需要借助外部存储媒介来实现集群单一

  • 静态内部类为什么能保证单例和线程安全
    外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。只有当getInstance()方法第一次被调用时,才会去初始化INSTANCE,第一次调用getInstance()方法会导致虚拟机加载内部类,在内存空间创建一个唯一的INSTANCE,这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化

  • 为什么枚举类是最好最安全的单例
    反射和序列化可以破坏单例
    1.枚举不可以被放射(具体查看放射代码)
    2.枚举序列化有专门的处理方法(具体查看ObjectInputStream代码)

  • Spring 是用哪种方式实现单例的
    由于单例模式私有构造所有不能被继承,Spring为了让单例可以继承,采用了单例注册表的方式实现单例模式,原理使用HashMap实现注册表

  • 代码

	//饿汉式
	public class Singletion{
		private statice Singletion instance = new Singletion();
		private Singletion(){}
		public static Singletion getInstance (){
			return instance;
		}
	}

	//懒汉式
	public class Singletion{
		public static Singletion getInstance(){
			//volatile 防止指令重排
			private volatile static Singleion instance = null;
			private Singletion(){}
			//双重检查加锁 先检查对象是否为为null 再进行同步,提高效率,避免每次创建对象都同步
			if(instance == null){
				synchronized(Singleton.class){
					if(instance == null){
						instance = new Singleton();  
					}
				}
				instance = new Singletion();
			}
			return instance;
		}
	}
	//静态内部类
	public class Singleton(){
		private Singleton(){}
		private static class SingletonInner	{
			private static Singleton instance = new Singleton();
		}
		public static Singleton getInstance(){
			return SingletonInner.instance;
		}
	}
	//枚举
	public enum Singleton{
		INSTANCE;
		public void method(){
			//具体业务逻辑
		}
	}
	public class Main{
		public static void main(String[] args){
			Singleton.INSTANCE.method();
		}
	}
	//反射攻击
	public class SingletionAttack(){
		public static void main(String[] args) throws 	Exception{
			Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
			//取消检查Java语言控制权限 例如:private
        	constructor.setAccessible(true);
        	Singleton singleton = constructor.newInstance();
        	Singleton singleton1 = constructor.newInstance();
        	System.out.println(singleton1 == singleton);
		}
	}
	//序列化攻击
	public static void main(String[] args) throws Exception {
        ObjectOutputStream outputStream = new ObjectOutputStream(
                new FileOutputStream("fileName")
        );
        Singleton instance = Singleton.getInstance();
        outputStream.writeObject(instance);

        ObjectInputStream inputStream = new ObjectInputStream(
                new FileInputStream("fileName")
        );
        Singleton instance2 = (Singleton) inputStream.readObject();
        System.out.println(instance == instance2);
    }
  • 源码中的案例
//可以获得系统环境变量、java版本号、运行其它程序的文件
public class Runtime {
 	private static Runtime currentRuntime = new Runtime(); 
	public static Runtime getRuntime() {
 		return currentRuntime;
 	}
 	private Runtime() {}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值