来看看单例模式

转载 2015年07月09日 11:02:44

Singleton pattern. 首先这没有被lazy initialization,在程序启动时(class Smarty被load)就会创建你的static instance,拖慢启动速度。

要解决lazy initialization, 就得这么写:

public class Smarty {
    private static Smarty instance;
    private Smarty() {}
    public static Smarty getInstance() {
        if(instance == null)
            instance = new Smarty();
        return instance;
    }
}

好了,现在instance只会在第一次getInstance被call的时候被创建。但是不好意思,多线程的情况下咋办?恩,似乎应该这样:

public class Smarty {
    private static Smarty instance;
    private Smarty() {}

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

看起来不错了,但是每次调用getInstance()都需要synchronized,似乎还可以改进:

public class Smarty {
    private static Smarty instance;
    private Smarty() {}

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

这样行了吗?好像可以了,但是有个bug,十个线程都进行了null check,但都还没进入synchonized block,大家一起排队等着吃果果。于是十个Smarty排着队被产出来了。不行。那这样呢:

public class Smarty {
    private static Smarty instance;
    private Smarty() {}

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

你们不是排队等着进来吃果果吗?进来了我再来check一次,这下不可能产出10个了吧。看起来已经完美了,可惜还是不行。这个可能不太好理解,但是下面这一行不是atomic的操作,它实际被分成几个步骤:allocate memory, assign allocated memory to instance ref, initialize the object Smarty into the allocated memory.
instance = new Smarty();
所以说如果线程1卡在第三步那里,线程2高高兴兴滴进来拿instance了,他会拿到一个还没煮好的蛋,吃下去,完蛋了。

有个keyword,可能一般你很少用到,叫volatile:

public class Smarty {
    private static volatile Smarty instance;
    private Smarty() {}

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

volatile是什么鬼?看看定义:
What is the Java volatile keyword?
Essentially, volatile is used to indicate that a variable’s value will be modified by different threads.
Declaring a volatile Java variable means:
The value of this variable will never be cached thread-locally: all reads and writes will go straight to “main memory”;
Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.
第二点,正是我们需要的,我还没煮完的鸡蛋你先别拿。

恩,终于可以了。但是,据说大部分JVM的implementation并不尊重volatile的规则。完蛋啦,搞了半天还是没法确定可以完美做singleton。

别紧张,这样写就没问题了。正确的Java Singleton 写法:

public class Smarty {
    private Smarty() {}

    private static class SmartyLoader {
        private static final Smarty instance = new Smarty();
    }

    public static Smarty getInstance() {
        return SmartyLoader.instance;
    }
}

因为Inner class的loading是在它第一次被调用的时候。合着整了半天就是这么简单。

还有一种写法,Java 5之后可用:

public enum Smarty {
    INSTANCE;
}

就是这么简单粗暴直接。下次碰到谁装逼说什么double locking singleton的,上去piapia俩巴掌,甩个enum过去到他脸上,瞬间B格爆满了有没有???

单例模式,你知道的和你所不一定知道的一切

简介 写这篇文章的目的呢,其实很简单,就是让更多的人明白,更加透彻的理解单例模式,或许大家以为单例模式嘛,大家都会些,简简单单,就那么两种,懒汉式或者说恶汉式,在多了解一点的,懒汉式和恶汉式的结合版...
  • u011546655
  • u011546655
  • 2016年01月02日 13:41
  • 1424

Java单例模式——并非看起来那么简单

Java中单例(Singleton)模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器和控制器常被设计成单例模式。单例模式有很多好处,它能够避免...
  • goodlixueyong
  • goodlixueyong
  • 2016年07月20日 23:48
  • 25039

从cocos2d-x看设计模式::单例模式

cocos2d-x是一个开源的跨平台游戏引擎,csdn上有很多很好的学习资料分享,这里便不详细讲述。 开源的引擎有很多的好处,其中之一就是可以个人对引擎进行修改,增添适合的特性和功能,增强独特性...
  • u011231445
  • u011231445
  • 2013年06月30日 19:05
  • 1148

理解JAVA中的单例模式 --->花1分钟看看

理解JAVA中的单例模式   欢迎加入我的qq群1543150073获得更多加瓦和职场信息!我帮你! 单例模式简单说就是:同一个对象,不用去new多个对象。减少内存消耗!        &对于J...
  • ml5271169588
  • ml5271169588
  • 2011年10月17日 14:24
  • 1077

单例模式不是一件小事,快回来看看

达人科技 2017-01-22 16:34 上次写了一篇《单例模式那件小事,看了你不会后悔》的文章,总结了常用的单例模式的实现。本文是上文的延续,单例模式绝不是一件小事,想弄清楚,真不是那么简单...
  • u011277123
  • u011277123
  • 2017年01月23日 08:59
  • 108

java中的单例模式

  • 2017年05月21日 22:02
  • 5KB
  • 下载

单例模式SingletonMode

  • 2015年08月04日 00:00
  • 10KB
  • 下载

iOS单例模式

  • 2015年08月01日 17:34
  • 62KB
  • 下载

单例模式的扩展及其应用

  • 2017年12月03日 16:06
  • 38KB
  • 下载

单例模式(Singleton)的6种实现

  • 2017年11月02日 11:14
  • 1.17MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:来看看单例模式
举报原因:
原因补充:

(最多只允许输入30个字)