• 单例模式总结


    昨天翻了本设计模式的书,发现单例模式竟然有点弄不明白了,抓紧查资料补上,这里总结下。

    1:

    class Singleton
    {
    private static Singleton instance;
    private Singleton()
    {
    //
    }

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

    注意:构造函数私有,方法静态

    问题:无法保证线程安全,有多个线程访问getInstance方法的时候可能产生多个Singleton对象。

    2:

    可以给getInstance方法添加同步:

    public static synchronized Singleton getInstance()
    {
    if (instance == null) //1
    instance = new Singleton(); //2
    return instance; //3
    }

    这样能满足需求,但是会带来性能上的损失。一般同步的方法比非同步的方法效率要低上百倍

    3:

    然后是懒汉式的单例模式:

    class Singleton
    {
    private static Singleton instance = new Singleton();
    private Singleton()
    {
    //
    }

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

    这种方法能保证instance实例在Singleton类第一次加载的时候初始化,解决了同步问题

    进一步的要求可能是不想让instance对象在类加载的时候初始化,而在使用getInstance方法的时候才初始化

    4:

    双重锁

    public static Singleton getInstance()
    {
    if (instance == null)
    {
    synchronized(Singleton.class) { //1
    if (instance == null) //2
    instance = new Singleton(); //3
    }
    }
    return instance;
    }

    这种方法能保证instance只被初始化一次。但是由于JVM内部的问题,该方法还是有漏洞的。

    假设线程1进入到步骤2,执行步骤3未完成,会先将instance设为非null值。

    这时候线程2会在判断instance==null的时候失败,返回一个不完整的intance对象

    5:

    既要lazy loading,又要同步~

    Bob Lee提出了一种方法:

    public class Singleton {
    private Singleton(){
    }
    static class SingletonHolder {
    static Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
    return SingletonHolder.instance;
    }
    }

    在该方法中,Singleton有一个静态内部类,内部类在外部类加载的时候并不会加载,只有在调用getInstance方法的时候加载SingletonHolder类。

    如上面的程序还是可能有问题:

    Singleton.SingletonHolder sh = new Singleton.SingletonHolder();
    Singleton instance
    = Singleton.SingletonHolder.instance;
    instance
    = sh.instance;

    上面的代码是可以访问SingletonHolder的内容的~~

    所以进一步的把SingletonHolder设为private的应该会更好。

    所以最后的代码如下:

    public class Singleton {
    private Singleton(){
    }
    private static class SingletonHolder {
    static Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
    return SingletonHolder.instance;
    }
    public static void main(String [] args)
    {
    Singleton.getInstance();
    }
    }

  • 相关阅读:
    struts2自定义拦截器之过滤不良言论---http500可能的问题所在
    bzoj4205[FJ2015集训] 卡牌配对
    bzoj1562[NOI2009] 变换序列
    bzoj1433[ZJOI2009] 假期的宿舍
    bzoj2150 部落战争
    从bzoj2463到bzoj1443和bzoj2437 博弈+二分图匹配
    bzoj4554[Tjoi2016&Heoi2016] 游戏
    bzoj1059[ZJOI2007] 矩阵游戏
    bzoj1143[CTSC2008] 祭祀river
    bzoj3175[Tjoi2013] 攻击装置
  • 原文地址:https://www.cnblogs.com/macula7/p/2003225.html
Copyright © 2020-2023  润新知