单列模式

1、什么是单列模式

单列模式(Singleton)保证一个类仅有一个实例,并提供一个访问的全局访问点,这种类型的设计模式属于创建型模式。在开发中,会经常遇到一个全局使用的类频繁地创建与销毁,这会非常浪费系统的内存资源,而且容易导致错误甚至一定会产生错误,所以我们单例模式所期待的目标或者说使用它的目的,是为了尽可能的节约内存空间,减少无谓的GC消耗,并且使应用可以正常运作。
结构图

2、实现方式

2.1、懒汉模式,线程不安全

最基本的实现方式,这种实现最大的问题就是不支持多线程。

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

针对懒汉模式线程不安全的问题,我们自然想到了,在getInstance()方法前加锁,于是就有了第二种实现

2.2、懒汉模式,线程安全

能够在多线程中很好的工作,打补丁方式写出来的结构效率很低,多数情况下不需要同步。

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

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

因为加了synchronized为独占排他锁,并发性能差,于是为了解决这个问题又有第三种实现

2.3、饿汉式

在类加载的时候,就完成了对象的初始化,类加载保证了他们天生是线程安全的

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {
        return instance;
    }
}

没有达到Lazy Loading的效果,如果从始至终从未使用过这个实例,则会造成内存的浪费,那如何解决这个问题呢?

2.4、静态内部类

Singleton 类被装载了,instance 不一定被初始化,只有在调用的时候才进行加载,达到了类似懒汉模式的效果,而这种方法又是线程安全的。

public class Singleton {

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton (){}
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

2.5、枚举

枚举实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化和线程安全的

public enum Singleton {

    INSTANCE;

    public void action() {

    }
}
调用
Singleton.INSTANCE.action();

2.6、双重校验锁法

采用双锁机制,安全且在多线程情况下能保持高性能

public class Singleton {

    private volatile static Singleton singleton;
    
    private Singleton (){}
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

3、总结

推荐使用3-6的实现方式,当然并不是说1-2不能使用,具体的还需要根据业务场景来使用,例如不需要再多线程使用的可以根据1来实现;需要支持序列化的可以使用5来实现,一般情况下建议使用3来实现

原文地址:https://www.cnblogs.com/fomin/p/9672075.html