1.什么是单例模式?
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2.单例模式分为几种?
饿汉式单例(立即加载):在单例类被加载时候,就实例化一个对象并交 给自己的引用;
懒汉式单例(延迟加载):只有在真正使用的时候才会实例化一个对象并交给自己的引用。
3.单例模式的优点和缺点?
在内存中只有一个对象,节省内存空间;
避免频繁的创建销毁对象,可以提高性能;
避免对共享资源的多重占用,简化访问;
为整个系统提供一个全局访问点。
缺点:
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
4.使用场景?
有状态的工具类对象;
频繁访问数据库或文件的对象;
当您想控制实例数目,节省系统资源的时候
5.单例模式的线程安全?
单线程都是安全的
多线程:
饿汉式在多线程是天生安全的(因为线程访问单例对象之前就已经创建好了)
懒汉式是线程不安全的(因为多个线程同时进入单例类就会创建出多个实例,违背单例模式的初衷)
6.懒汉式是线程不安全怎么办?
用内部类实现延迟加载
1.synchronized方法(运行效率会很低,因为同步块的作用域有点大,而且锁的粒度有点粗。同步方法效率低)
2.使用双重检查模式实现懒汉式单例 (保证了单例,而且切实提高了程序运行效率)
3.使用ThreadLocal实现懒汉式单例
7.双重检查必须为什么使用volatile修饰?
使用volatile实例化能够对所有线程立即可见,防止指令重排序。
因为new对象分为三个步骤而且不是原子性的,可能会导致指令重排序(比如先执行第二步)
步骤1:在堆内存申请一块内存空间;
步骤2:初始化申请好的内存空间;
步骤3:将内存空间的地址赋值给 singleton;
8.为什么使用volatile 修饰了引用还用synchronized 锁?
如果多线程访问的情况下会导致三个步骤中断,synchronized 锁就是防止这三个步骤中断的(一个一个来)