乐趣区

关于设计模式:设计模式单例模式

1. 单例模式介绍

单例模式提供了一种创建对象的最佳形式。
由某类负责创立本人的对象,并提供该对象的拜访形式,以确保该对象是该类惟一的实例。

(1) 实用状况:

存在一个全局应用的类被频繁的创立和销毁时,能够思考应用单例模式。

(2) 长处:

在堆中有且仅有一个实例,防止了频繁创立销毁以及保留的内存开销。

(3) 毛病:

没有接口,不能继承。
它在类的外部创立了本人的对象,这与繁多职责准则抵触,它原本不应该关怀内部是怎么实例化它的。

2. 单例模式实现

(1) 懒汉式(线程不平安)

先来看一种最简略的单例模式:

public class Singleton {
    private static Singleton instance;

    // 公有构造方法
    private Singleton() {}

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

为什么叫懒汉,因为它不急着创立实例,而是等到断定为空的时候才去创立

它最大的问题就是线程不平安,因为可能会有多个线程断定 instance == null,从而创立多个实例,严格意义上说,它并不能算单例模式。

(2) 懒汉式(线程平安)

上边的实现是线程不平安的,那给 getSingleton 办法减少 synchronized 不就行了吗:

public class Singleton {
    private static Singleton instance;

    // 公有构造方法
    private Singleton() {}

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

这样做的确是能够保障线程平安的,然而加锁会影响效率
其实除了第一次须要创立之外,后续的加锁就没有意义了

(3) 饿汉式

饿汉式指的是在类加载的时候,就间接创立了实例:

public class Singleton {private static Singleton instance = new Singleton();

    // 公有构造方法
    private Singleton() {}

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

这是比拟罕用的形式,也能够保障线程平安
然而在类加载的时候就实例化的话,万一它很耗费资源,就有点节约内存

(4) 双重校验锁

应用双重校验锁的形式能同时保障线程平安和高性能:

public class Singleton {
    // 留神这里的 volatile
    private volatile static Singleton instance;

    // 公有构造方法
    private Singleton() {}

    public static Singleton getSingleton() {
        // 第一次判断是否为空,为空才创立,否则间接返回
        if (instance == null) {synchronized (Singleton.class) {
                // 第二次判断是否为空,避免已被其余线程实例化之后反复实例化
                if (instance == null) {instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

这种形式中判断了两次 instance == null:
第一次判断是否为空,为空才创立,否则间接返回
第二次判断是否为空,避免已被其余线程实例化之后反复实例化
这里的要害是在申明 instance 变量的时候,减少了 volatile 关键字

volatile 有两个作用:

  1. 保障了不同线程对这个变量进行操作时的可见性,即一个线程批改了某个变量的值,这新值对其余线程来说是立刻可见的。但如果对该变量执行的是非原子操作,它不能保障线程平安
  2. 禁止指令重排序
退出移动版