懒汉式:
public class Singleton {
/*
* 使用private的原因是确保不让外界调用该类的构造方法,生成多余的对象*/
private Singleton() {}
/*
* private 禁止外部类调用该实例,防止对该实例对象进行修改操作
* 使用volatile的原因是防止在jvm层面对生成实例对象时,指令的重排序问题
* 将instance = null,该种设计方式是一种“懒汉式”的设计,只有使用的时候才会产生实例对象*/
private static volatile Singleton instance = null;
public static Singleton getInstance() {
/*
* 第一层检查:检查是否已经创建了对象,如果创建了,直接拿到该对象,不需要同步*/
if(instance == null) {
synchronized("lock") {
if(instance == null)
{
/*
* instance = new Singleton();在jvm层面做了3个步骤:
* 1. 为instance在堆内存中开辟一块内存空间
* 2. 调用Singleton的构造方法对成员变量进行初始化操作
* 3. 将instance的指针指向刚才开辟的堆空间(这一步执行完以后,instance才不为null)
* 但是在jvm对指令进行优化时,有可能将2,3步骤进行调换,产生的后果就是:当第一个线程操作完3,
* 但还没来得及操作2时,第二个线程判断instance已经不为null了,直接拿走,但实际上里面的
* 成员变量还没来得及初始化,所以会导致操作错误。
* 加上volatile关键字的目的是:1.保证了成员变量的可见性 2.禁止jvm对指令的重排序优化*/
instance = new Singleton();
}
}
}
return instance;
}
}
饿汉式:
/*
* 该设计为单例模式中饿汉式的初级版本,所谓饿汉式:
* 在类加载时,就会实例化一个实例对象*/
public class Singleton1 {
private Singleton1() {}
/*
* static 在类加载的时候,生成了一个实例对象,该种方式的缺点:
* 1. 无法达到需要使用时再创建的效果,如果该实例对象非常大,会消耗不必要的系统资源。
*/
private static Singleton1 instance = new Singleton1();
public static Singleton1 getInstance() {
return instance;
}
}
/*
* 升级版的饿汉式设计,可以解决初级版本的不足*/
class Singleton2 {
private Singleton2() {}
/*
* 采用内部类的形式去生成一个实例对象,这种方式做到了,只有当调用getInstance();时,才会产生实例对象*/
private static class SingletonHolder {
private static final Singleton2 instance = new Singleton2();
}
public static Singleton2 getInstance() {
return SingletonHolder.instance;
}
}