单例模式有5种实现方式:饿汉、懒汉、双重校验锁、静态内部类和枚举
/**
*
* --------------|------------|-------------|--------------|
* 单例模式实现 |是否线程安全 |是否为懒加载 |是否防止反射构建 |
* ------------|-------------|------------|--------------|
* 双重锁检验 | 是 | 是 | 否 |
* -----------|-------------|------------|-------------|
* 静态内部类 | 是 | 是 | 否 |
* ----------|-------------|------------|------------|
* 枚举 | 是 | 否 | 是 |
*
*/
// 一、饿汉
// 优点:类加载的时候创建一次实例,避免了多线程同步问题
// 缺点:即使单例没被用到也会创建,浪费内存
public class Singleton {
//饿汉普通
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
//饿汉变种
private static Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton(){};
public static Singleton getInstance(){
return instance;
}
}
//二、懒汉--(线程非安全)
// 优点:需要时才去创建
// 缺点:没有考虑线程安全问题,多个线程并发调用getInstance,可能会创建多个实例
class Singleton2{
private static Singleton2 instance = null;
private Singleton2(){}
public static Singleton2 getInstance(){
if(instance == null){
return new Singleton2();
}
return instance;
}
}
//懒汉--(线程安全)
// 缺点:性能问题,添加了synchronized的函数比一般方法慢得多,若多次调用getInstance,则累积的性能损耗特别大。
class Singleton3{
private static Singleton3 instance = null;
private Singleton3(){}
public static synchronized Singleton3 getInstance(){
if(instance == null){
return new Singleton3();
}
return instance;
}
}
//三、双重校验
/**
* 隐患:(此处涉及到JVM的指令重排)
* Java中的 instance = new Singleton(),会被编译器编译成以下JVM指令
* memory = allocate(); //1、分配对象内存空间
* ctorInstance(memory); //2、初始化对象
* instance = memory; //3、设置instance指向刚才分配的内存地址
* 但是这些指令并不是一成不变的,可能会经过JVM和CPU的优化而改变
* memory = allocate(); //1、分配对象内存空间
* instance = memory; //3、设置instance指向刚才分配的内存地址
* ctorInstance(memory); //2、初始化对象
* 当线程A执行完 1、3指令后,instance对象还未初始化,但已经不再指向null。此时如果线程B抢占CPU资源,
* 执行if(instance == null) 的结果会返回false,从而返回一个没有初始化完成的对象
*
* 解决方案:volatile(只有成员变量才能使用它)
* 作用:
* ①:多线程主要围绕可见性和原子性展开,使用volatile修饰变量,保证了其在多线程之间的可见性,即
* 每次读取到的volatile变量,一定是最新的数据
* ②:使用volatile会禁止JVM指令重排序,在一定程度上降低了代码执行效率。
*
*
*/
class Singleton4{
private static Singleton4 instance = null;
private Singleton4(){}
public static Singleton4 getInstance(){
if(instance == null){
synchronized(Singleton4.class){
if(instance == null){
return new Singleton4();
}
}
}
return instance;
}
}
//使用volatile修饰成员变量
class Singleton5{
private static volatile Singleton5 instance = null;
private Singleton5() {}
public static Singleton5 getInstance(){
if(instance == null){
synchronized (Singleton5.class){
if(instance == null){
return new Singleton5();
}
}
}
return instance;
}
}
//第四种:静态内部类
class Singleton6{
private static class LazyHolder{
private static final Singleton6 instance = new Singleton6();
}
private Singleton6(){}
public static Singleton6 getInstance(){
return LazyHolder.instance;
}
}
//第五种:枚举
//优点:既能避免多线程同步问题,又能防止反序列化重新创建新的对象。
enum Singleton7{
INSTANCE;
public void xx(){}
}