你真的会用单例模式吗

转载请注明出处:http://tedyin.me/2016/03/13/singlton-pattern/

今天给大家介绍一下单例模式,就是这个出场率特别高的模式,是个程序员基本都用过他,没用过至少也都知道他。可是我们真的了解他吗?

单例模式通常的实现方式分为以下两种:

饿汉式

public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton newInstance(){
        return instance;
    }
    public void doSomething(){
        // Do something ...
     }
}

饿汉式是最简单的实现方式,这种实现方式适合那些在初始化时就要用到单例的情况,这种方式简单粗暴,如果不单例初始化非常快,而且占用内存非常小的时候这种方式是比较合适的,直接在应用启动时加载并初始化。
但是,如果单例初始化的操作耗时比较长而应用对于启动速度又有要求,或者单例的占用内存比较大,再或者单例只是在某个特定场景的情况下才会被使用,而一般情况下是不会使用时,使用饿汉式的单例模式就是不合适的,这时候就需要用到懒汉式的方式去按需延迟加载单例。

懒汉式

public class Singleton{
    private static Singleton instance = null;    
    private Singleton(){}
    public static newInstance(){
        if(null == instance){
            instance = new Singleton();
        }
        return instance;
    }
    public void doSomething(){
        // Do something ...
    }
}

懒汉式饿汉式的最大区别就是将单例的初始化操作,延迟到需要的时候才进行,这样做在某些场合中有很大用处。比如某个单例用的次数不是很多,但是这个单例提供的功能又非常复杂,而且加载和初始化要消耗大量的资源,这个时候使用懒汉式就是非常不错的选择。

多线程下的单例模式

上面介绍了一些单例模式的基本应用方法,但是上面所说的那些使用方式都是有一个隐含的前提,那就是他们都是应用在单线程条件下,一旦换成了多线程就有出错的风险。
如果在多线程的情况下,饿汉式不会出现问题,因为JVM只会加载一次单利类,但是懒汉式可能就会出现重复创建单利对象的问题。为什么会有这样的问题呢?因为懒汉式在创建单例时是 线程不安全的,多个线程可能会并发调用他的newInstance方法导致多个线程可能会创建多份相同的单例出来。

那有没有办法,使饿汉式的单利模式也是线程安全的呢?答案肯定是有的,大家通常会使用加同步锁的方式去实现,但是这样实现起来比较麻烦。那么有没有更好的实现方式呢?能问这个问题那必须是有的,否则就得打脸了。 我们可以利用JVM的类加载机制去实现。在很多情况下JVM已经为我们提供了同步控制,比如:

  • static{}区块中初始化的数据
  • 访问final字段时
  • ...
  • 等等

因为在JVM进行类加载的时候他会保证数据是同步的,我们可以这样实现:

采用内部类,在这个内部类里面去创建对象实例。这样的话,只要应用中不使用内部类 JVM 就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载和线程安全。

实现代码如下:

public class Singleton{
    //内部类,在装载该内部类时才会去创建单利对象
    private static class SingletonHolder{
        public static Singleton instance = new Singleton();
    }

    private Singleton(){}

    public static Singleton newInstance(){
        return SingletonHolder.instance;
    }

    public void doSomething(){
        //do something
    }
}

这样实现出来的单例类就是线程安全的,麻麻再也不用担心我的单例不是单例了。

使用枚举实现单例模式

除了上述的单例模式的实现方式外,我们还可以通过枚举类来实现单利模式,这也是Effective Java中推荐的方式。

使用枚举类型实现单例模式如下:

public enum Singleton{
    //定义一个枚举的元素,它就是Singleton的一个实例
    instance;

    public void doSomething(){
        // do something ...
    }    
}

用枚举实现是不是更简单呢?枚举方式实现的单例模式也是线程安全的,所以大家不用担心多线程问题,可以大胆去用。

以上就是单例模式的使用,现在完全可以说,你真的会用单例模式了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 一、简介: 单例模式:确保一个类只有一个实例,并提供一个全局访问点. 单例模式是所有设计模式中最简单的一个,也是大...
    唠嗑008阅读 2,218评论 14 35
  • 单例模式(SingletonPattern)一般被认为是最简单、最易理解的设计模式,也因为它的简洁易懂,是项目中最...
    成热了阅读 4,231评论 4 34
  • 1 场景问题# 1.1 读取配置文件的内容## 考虑这样一个应用,读取配置文件的内容。 很多应用项目,都有与应用相...
    七寸知架构阅读 6,684评论 12 68
  • 1.单例模式概述 (1)引言 单例模式是应用最广的模式之一,也是23种设计模式中最基本的一个。本文旨在总结通过Ja...
    曹丰斌阅读 2,893评论 6 47
  • 细雨随轻风飘洒 黄叶携水滴零落 思念的串珠绵柔有致 隔窗溅入心窝 雀歇屋檐下 车奔上高速 船留在水中 纵横又宁静 ...
    富景流觞阅读 143评论 0 0