一 单例模式
1.1 单例模式
单例模式:保证一个类在全局只有一个实例,并对外提供一个访问接口。
1.2 使用场景
1 需要统计全局数据
2 创建一个对象需要耗费资源过多,比如IO或者数据库资源
3 一般工具类都会单例模式
二 优点和缺点
优点:
内存只有一个或者极少实例,减少了频繁创建对象的开销,节省内存等资源,有利于提升性能
缺点:
单例模式扩展比较困难,一般都需要修改代码
三 代码实例
单例模式的七种实现方式:
3.1饥汉式
public class SingletonA {
private static SingletonA singletonA = new SingletonA();
private SingletonA(){ }
public static SingletonA getInstance(){
return singletonA;
}
}
3.2 懒汉式,非线程安全
public class SingletonB {
private static SingletonB singletonB = null;
private SingletonB(){ }
public static SingletonB getInstance(){
return singletonB == null ? new SingletonB() : singletonB;
}
}
3.3 懒汉式,线程安全
public class SingletonC {
private static SingletonC singletonC = null;
private SingletonC(){ }
public static SingletonC getInstance(){
synchronized (SingletonC.class) {
return singletonC == null ? new SingletonC() : singletonC;
}
}
}
3.4 懒汉式,双重检验锁
public class SingletonD {
private static SingletonD singletonD = null;
private SingletonD(){ }
public static SingletonD getInstance(){
if (singletonD == null) {
synchronized (SingletonD.class) {
return singletonD == null ? new SingletonD() : singletonD;
}
}
return singletonD;
}
}
3.5 静态内部类实现
通过JVM类加载机制来保证初始化实例的时候只存在一个线程,避免线程安全问题,饿汉式的Singleton类被加载时,就会实例化,而静态内部类这种,当Singleton类被加载时,不会立即实例化,调用getInstance() 方法才会装载SingletonHolder类,从而完成Singleton的实例化。
public class SingletonE {
private SingletonE(){ }
public static final SingletonE getInstance(){
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder {
private static final SingletonE INSTANCE = new SingletonE();
}
}
3.6 基于volatile实现的单例(最终解决方案)
new的时候首先分配内存,然后在分配的内存上创建单例实例,最后将引用指向这个实例。但是可能存在指令重排序的问题,有可能首先分配内存,再将引用指向这个实例,最后分配的内存上创建单例实例
因为new这个过程并不是原子性的,所以可能导致将引用指向这个实例线程切换了,导致返回的对象是null
解决办法: 避免指令重排序
final? 只能避免指令重排序,不能保证可见性
volatile: 既可以保证可见性,又能避免指令重排序
public class Singleton4 {
private static volatile Singleton4 instance = null;
private Singleton4() {
}
public static Singleton4 getInstance() {
if (instance == null) {
synchronized (Singleton4.class) {
return instance == null ? new Singleton4() : instance;
}
}
return instance;
}
}