设计模式-单例模式

Posted zhou-920644981

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-单例模式相关的知识,希望对你有一定的参考价值。

返回上一级目录:Java设计模式

单例模式,所谓单例,就是应用只有一个实例对象,该类具有以下特点:

  1. 构造器私有化,保证只有自己才能通过构造器创建实例对象
  2. 持有实例对象的引用,就是最终提供出去的单例实例
  3. 提供一个方法获取该单例实例

下面是常用的几种实现:

1、懒汉式

  这是最简单也最容易想到的一种方式。缺点就是不是线程安全,多个线程环境下可能会生成多个实例对象。

public class Singleton1 {

    private static Singleton1 instance;

    /**
     * 构造方法私有化
     */
    private Singleton1() {

    }

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

        return instance;
    }
}

2、懒汉式(线程安全)

  鉴于懒汉式的缺点,一个改进的方法就是在对getInstance()加锁,确保同时只有一个线程调用。

public class Singleton2 {

    private static Singleton2 instance;

    /**
     * 构造方法私有化
     */
    private Singleton2() {

    }

    /**
     * 弥补了SimpleSingleton1线程安全问题,但是效率很低,任何时候需要instance只能有一个线程去访问getInstance(),
     * 其实只需要在第一次创建对象时候同步,保证只有一个实例被创建
     *
     * @return
     */
    public static synchronized Singleton2 getInstance() {
        if (instance == null) {
            instance = new Singleton2();
        }

        return instance;
    }
}

3、双重校验锁

  这种方式能很好的解决了懒汉式线程安全和效率的问题,实际应用中通常推荐使用这种方式。

public class Singleton3 {

    /**
     * volatile是禁止new Singleton3()发生指令重排序
     * instance = new Singleton3()在jvm中做了3件事:1.分配内存,2.调用构造方法初始化成员变量,3.将instance指向分配的内存空间
     * jvm在编译时可能对上面步骤2,3重排序,如果先执行3,这时候instance != null,可能被其他线程拿到一个没有初始化完的对象使用而出错
     */
    private static volatile Singleton3 instance;

    private Singleton3() {

    }

    /**
     * 多个线程进入第一个if,只有一个线程进入同步块创建对象,如果其他线程获得锁进入同步块,不判断instance是否已经被创建,
     * 则有可能会创建多个对象
     *
     * @return
     */
    public static Singleton3 getInstance() {
        if (instance == null) {
            synchronized (Singleton3.class) {
                if (instance == null) {
                    instance = new Singleton3();
                }
            }
        }

        return instance;
    }
}

4、饿汉式

  一开始就初始化好一个静态的实例,在其他调用者需要时直接返回。缺点是创建比较简单,不能依赖其他的参数来创建实例对象。

public class Singleton4 {

    private static Singleton4 instance = new Singleton4();

    private Singleton4() {

    }

    /**
     * 类加载后就被初始化,不能依赖其他参数来创建实例
     *
     * @return
     */
    public static Singleton4 getInstance() {
        return instance;
    }
}

5、静态内部类

  静态内部类不会随着外部类加载而加载,当getInstance()被调用时,内部类SingletonHolder被加载,接着其静态属性instance初始化。这样不仅保证了延迟加载,也保证了线程安全,也经常被推荐使用。

public class Singleton5 {

    private Singleton5() {

    }

    private static class SingletonHolder {
        private static Singleton5 instance = new Singleton5();
    }

    /**
     * 使用SingletonHolder时候才会加载内部静态类,所以也是懒汉式,类加载机制又保证了多线程的安全性
     *
     * @return
     */
    public static Singleton5 getInstance() {
        return SingletonHolder.instance;
    }
}

返回上一级目录:Java设计模式

以上是关于设计模式-单例模式的主要内容,如果未能解决你的问题,请参考以下文章

常用代码片段

性能比较好的单例写法

你熟悉的设计模式都有哪些?写出单例模式的实现代码

单例模式以及静态代码块

设计模式之单例模式

设计模式之单例模式