单例模式的8种写法

1. 饿汉式,静态常量,可用

public class Singleton {

    private final static Singleton INSTANCE = new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
复制代码

优点:

  • 写法简单
  • 类加载的时候就完成了实例化

2. 饿汉式,静态代码块,可用

public class Singleton {

    private final static Singleton INSTANCE;

    static {
        INSTANCE = new Singleton();
    }

    private Singleton() {

    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
复制代码

3. 懒汉式,线程不安全,不可用

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
复制代码

缺点:

  • 线程不安全,多个线程会重复创建实例

4. 懒汉式,线程安全,同步方法,不推荐使用

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public synchronized static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
复制代码

缺点:

  • 效率低

5. 懒汉式,线程不安全,同步代码块,不可用

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}
复制代码

6. 双重检查,推荐面试使用

public class Singleton {

    private volatile static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
复制代码

优点:

  • 两次判断保证线程安全
  • 延迟加载,效率较高

为什么要用volatile?

new Singleton()新建对象实际上有3个步骤,使用volatile可以防止重排序。


7. 静态内部类,推荐使用

public class Singleton {

    private Singleton() {

    }

    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}
复制代码

优点:

  • 线程安全
  • 懒加载

8. 枚举,推荐使用(生产实践中最佳的单例写法)

public enum Singleton {

    /**
     * 实例
     */
    INSTANCE;

    /**
     * 其它的方法...
     */
    public void test(){

    }
}
复制代码

其它类如何使用?

public static void main(String[] args) throws InterruptedException {
    Singleton.INSTANCE.test();
}
复制代码

不同写法对比

  • 饿汉:简单,但是没有懒加载
  • 懒汉:有线程安全问题
  • 静态内部类:可用
  • 双重检查:面试用
  • 枚举:最好

枚举为什么是最好的方法

1. Joshua Bloch大神在《Effective Java》中明确表达过的观点:“使用枚举实现单例的方法虽然还没有广泛采用,但是单元素的枚举类型已经成为实现Singleton的最佳方法”。

2. 写法简单

3. 线程安全有保障

4. 避免反序列化破坏单例

各种写法的适用场合

  • 最好的方法是利用枚举,因为还可以防止反序列化重新创建新的对象;
  • 非线程同步的方法不能使用;
  • 如果程序一开始要加载的资源太多,那么就应该使用懒加载;
  • 饿汉式如果是对象的创建需要配置文件就不适用;
  • 懒加载虽然好,但是静态内部类这种方式会引入编程复杂性。
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享