1、什么是单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2、单例模式有什么好处
- 对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;
- 由于 new 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻 GC 压力,缩短 GC 停顿时间。
3、为什么不使用全局变量
如果对象非常消耗资源,并且程序某次的执行中一直没用,这样就造成了资源的浪费;此外,在程序中要尽量避免全局变量的使用,大量使用全局变量给程序的调试、维护等带来困难。
4、单例模式的实现
1)恶汉方式(线程安全)所谓 “饿汉方式” 就是JVM在加载这个类时就创建唯一的单例实例,不管用不用,典型的空间换时间,每次调用的时候,就不需要再判断,节省了运行时间。
public class Singleton {
//在静态初始化器中创建单例实例
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
2) 饱汉方式(非线程安全版)
public class Singleton {
private static Singleton instance;
private Singleton (){}
//没有加入synchronized关键字的版本是线程不安全的
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3) 饱汉(线程安全)每一次获取都会synchronized加锁这一层,会增加getInstance()的方法的时间消费,而且还可能会发生阻塞
public class Singleton {
private static Singleton instance;
private Singleton (){}
//没有加入synchronized关键字的版本是线程不安全的
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4)双重锁检查
public class Singleton {
//volatile保证
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
//检查实例,如果不存在,就进入同步代码块
if (instance == null) {
//只有第一次才彻底执行这里的代码
synchronized(Singleton.class) {
//进入同步代码块后,再检查一次,如果仍是null,才创建实例
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
5)静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
6)枚举类
public enum Singleton {
//定义一个枚举的元素,它就是 Singleton 的一个实例
INSTANCE;
public void doSomeThing() {
// method
}
}