Java 单例模式有哪些实现方式

实现方式 线程安全 并发性能好 可以懒加载 反射/序列化/反序列化安全
饿汉模式 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;
    }
}

你可能感兴趣的:(Java 单例模式有哪些实现方式)