单例模式
简介:单例模式是GoF23种设计模式中最常见的设计模式之一,无论是第三方类库,还是我们日常开发中都能看到他的影子。
单例与多例:
单例与多例问题是指,当多个用户访问某个类时,系统是为每个用户创建一个该类实例,还是整个系统无论多少用户访问,只创建一个该类实例。
线程安全问题是指,多个用户同时在访问同一个程序时,其对于某一数据的修改,会不会影响到其他用户中的该数据。若没有影响,则是线程安全的;若有可能影响,则是线程不安全的。
一、饿汉式
public class Singleton {
/**
* 在定义变量时候直接初始化对象
*/
private static Singleton singleton = new Singleton();
/**
* 私有构造不允许外部 new
*/
private Singleton() {
}
public static Singleton getInstance() {
return singleton;
}
}
饿汉式在类创建时就创建好了一个静态的对象提供系统使用,以后不再改变,能够百分百地保证singleton实例的唯一性。也就是说singleton在多线程的情况下不可能被实例化两次,但是singleton被ClassLoader加载后如果很长时间才被使用,如果一个类中的成员属性很多那么就会占用内存资源。
二 、懒汉式
public class Singleton {
/**
* 定义变量但是不直接初始化对象
*/
private static Singleton singleton = null;
/**
* 私有构造不允许外部 new
*/
private Singleton() {
}
public static Singleton getInstance() {
if (null == singleton) {
return new Singleton();
}
return singleton;
}
}
所谓的懒汉式方式就是在使用类的时候再去创建,这样就避免了类在初始化前提前创建—懒加载。但是这种方式在多线程下会出现问题,在多线程下可能出现多个实例。
三 、Volatile+Double-check
Volatile+Double-check 双重检测,它提供了一种高效的数据同步策略,那就是是首次初始化加锁,之后允许多个线程同时进行getInstance方法的调用,Volatile对变量对修饰可以禁止指令重排序,可以防止实例化资源时候出现空指针。
public class Singleton {
/**
* 定义变量但是不直接初始化对象
* 使用volatile修饰可以禁止指令冲排序
*/
private static volatile Singleton singleton = null;
/**
* 私有构造不允许外部 ---- new
*/
private Singleton() {
}
public static Singleton getInstance() {
if (null == singleton) {
synchronized (Singleton.class) {
if (null == singleton) {
return new Singleton();
}
}
}
return singleton;
}
}
四 枚举方式
public class Singleton {
private Singleton() {}
static enum SingletonEnum {
//创建一个枚举对象,该对象天生为单例
INSTANCE;
private Singleton instance;
/**
* 私有化枚举的构造函数
*/
private SingletonEnum() {
instance = new Singleton();
}
public Singleton getInstance() {
return instance;
}
}
/**
* 对外暴露一个获取User对象的静态方法
*/
public static Singleton getInstance() {
return SingletonEnum.INSTANCE.getInstance();
}
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1==instance2);
}
}