- 单例模式很简单,但是为什么会是高频面试题? 简单、常用,面试官需要的不是技术本身,而是你对如此简单的知识有自己不同的见解, 懒汉式、饿汉式、静态内部类、枚举式、双重检查锁、登记/注册式
单例模式是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点
- 隐藏其所有的构造方法,
- 提供全局的访问点
饿汉式
优点:简单、线程安全
缺点:浪费内存(当我们的单例对象数量不可控的时候,可能造成内存浪费)
public class Singleton {
//类加载的时候,单例对象已经被创建
private static Singleton instance = new Singleton();
//构造方法私有化
private Singleton (){}
//提供一个全局访问点
public static Singleton getInstance() {
return instance;
}
}
懒汉式
优点:节省资源、
缺点:非线程安全
两个线程按顺序进入判断,得到相同结果
两个线程在同一时间点,同时进入,会new两次,创建两个对象
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
同步锁,synchronized 限制资源访问,实现线程安全,但同时由于加锁,影响了代码性能,同一时间只能有一个访问,后面的都被堵塞,只能进入线程等待
public class Singleton {
private static Singleton instance;
private Singleton (){}
//加锁
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
因此就有了双重检查锁
优点:性能高、线程安全、避免了内存浪费
缺点:理解难度较高、代码不优雅、存在指令重排问题
public class Singleton {
private volatile static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
//控制要不要加锁、阻塞,主要是第一次
if (instance == null) {
synchronized(Singleton.class){
//控制要不要创建对象
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
又要性能高、又要线程安全、又要避免内存浪费、代码优雅,
因此有了静态内部类
优点:性能高、线程安全、避免了内存浪费、代码优雅
缺点:能被反射破坏
public class Singleton {
private SingleTon(){}
//巧妙的运用了java语法,类加载机制,内部类只有在使用的时候才加载
private static class SingleTonHoler {
private static SingleTon instance = new Singleton();
}
public static Singleton getInstance () {
return Singleton.instance;
}
}