单例模式

来源:互联网 发布:电脑绑定mac地址 编辑:程序博客网 时间:2024/06/03 23:02

单例模式——Singleton Pattern

定义:一个类只有一个实例,并且由该类自行实例化和向系统提供该实例。

单例模式类图

使用场景:

  1. 避免创建多个消耗资源较多的实例对象。
  2. 某个类只能有一个实例对象。

使用单例模式时要注意以下几点:

  1. 私有化构造函数
  2. 通过静态方法向外提供单例对象
  3. 注意线程安全问题
  4. 注意反序列化重新生成对象的问题
  • 实现方式一:饿汉式
/** * 饿汉式单例 */public class EagerSingleton {    private static final EagerSingleton instance = new EagerSingleton();    private EagerSingleton() { }    public static EagerSingleton getInstance() {        return instance;    }}

饿汉式不存在线程安全问题, 但不发实现延时加载,也就是即使还没使用单例对象,该对象都要随着类的加载而创建。


  • 实现方式二:懒汉式
/** * 懒汉式单例 */public class LazySingleton {    private static LazySingleton instance = null;    private LazySingleton() { }    public static synchronized LazySingleton getInstance() {        if (instance == null) {            instance = new LazySingleton();        }        return instance;    }}

懒汉式虽然实现了延时加载(第一次使用时才创建对象),但是为了解决线程安全问题,每一次获取单例时都要进行同步处理,影响性能。


  • 实现方式三:DCL
/** * DCL双重检查锁定 */public class DCLSingleton {    private volatile static DCLSingleton instance = null;    private DCLSingleton() { }    public static DCLSingleton getInstance() {        if (instance == null) {     //避免不必要的同步            synchronized (DCLSingleton.class) {                if (instance == null) {                    instance = new DCLSingleton();                }            }        }        return instance;    }}

DCL方式本质上还是懒汉式,为了解决每次获取单例时都要同步处理的问题,将同步方法改为了同步代码块。如果单纯这样就仍然存在同步问题,因此需要双重检查。第一次判断为了避免不必要的同步,第二次判断为了确保实例对象为null时才创建。(注意:代码中的单例对象使用了volatile关键字,使得该变量对不同线程都是可见的,即一个线程修改了该变量 的值,这个修改对其它线程是立刻可见的。)


  • 实现方式四:通过静态内部类创建单例对象
/** * 由内部类实例化单例对象 */public class Singleton {    private static class SingletonHolder {        private static final Singleton instance = new Singleton();    }    public static Singleton getInstance() {        return SingletonHolder .instance;    }}

这种由内部类创建单例对象的方式,既可以实现延迟加载,也避免了线程同步问题,是一种不错的实现方式。


  • 实现方式五:枚举
/** * 枚举单例 */public enum EnumSingle {    INSTANCE;}

枚举单例不存在线程安全问题,还能防止反序列化时重新生成对象的问题,但它跟饿汉式一样无法延时加载。

注意:单例类保证了对象的只有一个,同理,只要控制好类的实例对象的创建个数,那么这个类就是一个实例对象受控的多例类。

原创粉丝点击