单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。省略创建多个对象所花费的时间和内存空间。
单例模式类的两大特征
构造函数必须为 private ,确保单例不会在系统中的其他代码内被实例化。
实例成员变量和初始化方法必须为 static 。
饿汉方式
在类装载时,立即创建单例对象。
如果一直未被使用,内存空间被浪费;但每次调用时不需要判断,可以节省运行时间。
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {}
public static Singleton getInstance(){
return singleton;
}
// 在后方定义功能
}
枚举类实现。 更简洁,自动支持序列化机制,防止多次实例化。
public enum Singleton {
INSTANCE;
// 在后方定义功能
}
使用时直接使用 Singleton.INSTANCE 对象即可。
懒汉方式
在第一次被使用时,创建单例对象。
synchronized 关键字实现,加同步锁后再新建对象,保证线程安全。
public class Singleton {
private static Singleton singleton;
private Singleton (){
}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
// 在后方定义功能
}
双重锁结构实现,先判断实例对象是否存在,如果不存在不再需要加锁,大大提高了效率。
volatile 关键字用于防止指令重排序。创建对象的过程可能发生重排序,在未给初始化对象赋初值的情况下,就为设置实例对象指向刚分配的内存地址。其他线程在此时可能会通过!=null判断读取到未赋初值的内存空间。
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
// 在后方定义功能
}
static 内部类实现。 和枚举类原理类似,防止多次实例化。
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
// 在后方定义功能
}