美文网首页
从一生所爱到单例模式

从一生所爱到单例模式

作者: runningapple8 | 来源:发表于2018-02-25 16:21 被阅读0次

概要


好无聊,无聊到只能用学习来打发时间了。
刚刚听音乐,正好放到了一首我非常喜欢的歌 一生所爱。就是大话西游里面的那首。每每听到这首歌,心,痛。
咦,好像一生所爱和我今天要总结的单例模式关联不上了,不管了,下面直接开始总结,不然我的心就白白痛了啵。

饿汉式

个人以为饿汉式是实现单例最简单粗暴等方式了。无论是谁,随便拿一本 Java 书籍,只要看过前 30 页,就能写饿汉式的单例。原因很简单只要知道静态变量在类加载的时候就被创建了,那么任意定义静态变量并直接初始化,你不想单例都难了。

class SingletonHungry {
    private static SingletonHungry instance = new SingletonHungry();

    private SingletonHungry() {}

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

饿汉式的单例实现起来十分简单而且还是线程安全的,但是并没有延时初始化,这会对内存造成浪费,就像很多安卓手机应用,明明没用到,却在开机时候就在后台偷偷启动了。不过鉴于如今硬件升级速度之快,可以让我们不用那么关心这点内存问题。

懒汉式

懒汉式分两种,一种是线程不安全的,还有一种是线程安全的。
如下这段个单例在多线程环境下就有可能会出错。

//懒汉式 线程不安全
class SingletonLazy {
    private static SingletonLazy instance;

    private SingletonLazy() {}

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

多线程出错演示

接下来是线程安全的懒汉式

//懒汉式 线程安全
class SingletonLazySafe {
    private static SingletonLazySafe instance;

    private SingletonLazySafe() {}

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

看线程安全和不安全的两种实现方式代码其实没什么差别,唯一不同的地方就是线程安全的方式加了一个关键字 synchronized,用于确保 getInstance 方法线程安全。但是这样线程安全是安全了,那么如果接下来有上百上千个线程来访问这个方法,每个线程调用一次就把这个方法先锁一次,你说你死不死。所以这两种其实都不是实现单例的好方法。

双重校验模式 double-checked locking

说到底 双重校验模式 也是 懒汉式 的一种。它解决了上面懒汉式效率低下的问题。

class SingletonDCL {
    private static SingletonDCL instance;

    private SingletonDCL() {}

    public static SingletonDCL getInstance() {
        if (null == instance) {
            synchronized (SingletonDCL.class) {
                if (null == instance) {
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
}

可以从代码中看出,我们学聪明了,没有将整个 getInstance 方法给锁住,而是只锁创建实例的部分。另外进行了两次 null 判断。
这两次判断还是比较讲究的,第一次判断是否为 null 的意图很明显,就是为了如果实例已经存在那么我们就直接返回实例,不要再做任何多余的操作。
第二次判断是为了解决多线程情况下创建多个实例的问题。(假设一下没有这个判断,当两个线程 A,B 同时访问这个方法,A 线程先获取了锁,B 线程在等待。A 线程完成实例化操作,释放了锁,然后 B 线程开始执行实例化操作,这个时候因为没有判断 instance 已经被实例化过了,又重新实例化一遍,这就不是单例了。)
所以,双重校验模式才是真正的懒汉式,嗯!

登记式/静态内部类

使用静态内部类方式能达到双重校验模式一样的效果,而且实现更加简单。
这里用到了 Java 静态内部类的特性,加载类的时候,不会加载静态内部类,只有在使用的时候才会进行显示装载。

class SingletonRegister {
    private static class SingletonInner {
        private static final SingletonRegister INSTANCE = new SingletonRegister();
    }

    private SingletonRegister() {

    public static SingletonRegister getInstance() {
        return SingletonInner.INSTANCE;
    }
}

枚举方式

说实话,从没有在实际项目中看到用枚举方式实现单例的,不过这是 Effective Java 作者 Josh Bloch 提倡的方式。
这种方式实现起来简单的让人疑惑 这是单例吗?没错,还真是。

enum SingletonEnum {
    INSTANCE("url", "name", "pwd", "etc");
    private String url;
    private String name;
    private String pwd;
    private String etc;

    SingletonEnum(String url, String name, String pwd, String etc) {
        this.url = url;
        this.name = name;
        this.pwd = pwd;
        this.etc = etc;
    }

    public void doSomething() {
        System.out.println("do something");
    }

    public SingletonEnum getInstance() {
        return INSTANCE;
    }
}

总结

一般在实际项目中使用到单例模式时候,会以饿汉模式作为首选,如果有延时加载要求的那才会用内部类实现方式。如果有反序列化需求的,那么可以用枚举方式实现,毕竟 Enum 已经实现了 Serializable 接口。

总结好了,老朽要再去刷遍《大话西游》了。

相关文章

  • 从一生所爱到单例模式

    概要 饿汉式 个人以为饿汉式是实现单例最简单粗暴等方式了。无论是谁,随便拿一本 Java 书籍,只要看过前 30 ...

  • 单例模式

    单例模式是封装的一种形式,依靠单例模式调用被封装的属性和方法,因为使用单例模式的类无法生成实例(只能引用单例模式所...

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: Android Application 中使用单例模式:

  • python实现单例模式的5种方法

    单例模式 相信大家都知道单例模式 单例模式最初的定义出现于《设计模式》(艾迪生维斯理, 1994):“保证一个类仅...

  • Android设计模式总结

    单例模式:饿汉单例模式://饿汉单例模式 懒汉单例模式: Double CheckLock(DCL)实现单例 Bu...

  • 初识设计模式之单例模式

    此文为笔者个人的学习笔记,在学习部分博客、书籍、资料后所总结,仅供参考。 对单例模式的认识单例模式是什么单例模式的...

  • 2018-04-08php实战设计模式

    一、单例模式 单例模式是最经典的设计模式之一,到底什么是单例?单例模式适用场景是什么?单例模式如何设计?php中单...

  • 设计模式之单例模式详解

    设计模式之单例模式详解 单例模式写法大全,也许有你不知道的写法 导航 引言 什么是单例? 单例模式作用 单例模式的...

  • Telegram开源项目之单例模式

    NotificationCenter的单例模式 NotificationCenter的单例模式分析 这种单例模式是...

  • 单例模式Java篇

    单例设计模式- 饿汉式 单例设计模式 - 懒汉式 单例设计模式 - 懒汉式 - 多线程并发 单例设计模式 - 懒汉...

网友评论

      本文标题:从一生所爱到单例模式

      本文链接:https://www.haomeiwen.com/subject/noprxftx.html