实现方式 | 线程安全 | 并发性能好 | 可以懒加载 | 反射/序列化/反序列化安全 |
---|---|---|---|---|
饿汉模式 | Y | Y | N | N |
懒汉模式(不加锁) | N | Y | Y | N |
懒汉模式(加锁) | Y | N | Y | N |
双重校验锁模式 | Y | Y | Y | N |
静态内部类模式 | Y | Y | Y | N |
枚举类模式 | Y | Y | N | Y |
1)饿汉模式
1、线程安全(在类加载的时候就完成了实例化,避免了多线程的同步问题),调用效率高。
2、不可以懒加载,因为类加载时就实例化了,如果该实例没被使用,内存就浪费了。
class Singleton {
/**
* 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
*/
private static Singleton instance = new Singleton();
/**
* 私有构造方法
*/
private Singleton() {
}
/**
* 返回对象实例
*/
public static Singleton getInstance() {
return instance;
}
}
2)懒汉模式(不加锁)
1、线程不安全(假设对象还没被实例化,然后有两个线程同时访问,那么就可能出现多次实例化的结果),调用效率高。
2、可以懒加载,因为只有在方法第一次被访问时才会实例化。
class Singleton {
/**
* 声明变量
*/
private static Singleton singleton = null;
/**
* 私有构造方法
*/
private Singleton() {
}
/**
* 返回对象实例
*/
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
2)懒汉模式(加锁)
1、线程安全,调用效率低。
2、可以懒加载,因为只有在方法第一次被访问时才会实例化。
class Singleton {
/**
* 声明变量
*/
private static Singleton singleton = null;
/**
* 私有构造方法
*/
private Singleton() {
}
/**
* 返回对象实例
*/
public synchronized static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
4)双重校验锁模式
1、线程安全,调用效率高。
2、可以懒加载,因为只有在方法第一次被访问时才会实例化。
class Singleton {
/**
* volatile的作用:每次读取前必须先从主存刷新最新的值,每次写入后必须立即同步回主存当中
*/
private static volatile Singleton singleton = null;
/**
* 私有构造方法
*/
private Singleton() {
}
/**
* 返回对象实例
*/
public static Singleton getInstance() {
//此处检测singleton == null,是为了防止当singleton已经初始化后,还会继续调用同步锁,造成不必要的损耗
if (singleton == null) {
//加锁目的,防止多线程同时进入造成对象多次实例化
synchronized (Singleton.class) {
//为了在singleton == null的情况下创建实例,防止不必要的损耗
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
5)静态内部类模式
1、线程安全(因为这个类的实例化是靠静态内部类的静态常量实例化的,INSTANCE是常量,因此只能赋值一次),调用效率高。
2、可以懒加载,因为只有在方法第一次被访问时才会实例化。
class Singleton {
/**
* 私有构造方法
*/
private Singleton() {
}
/**
* 返回对象实例
*/
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* 写一个静态内部类,里面实例化外部类
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
}
6)枚举类模式
1、线程安全(在类加载的时候就完成了实例化,避免了多线程的同步问题),调用效率高。
2、不可以懒加载,因为类加载时就实例化了,如果该实例没被使用,内存就浪费了。
3、反射/序列化/反序列化安全
public enum SingletonEnum {
INSTANCE;
public SingletonEnum getInstance(){
return INSTANCE;
}
}
网友评论