美文网首页
设计模式之单例模式

设计模式之单例模式

作者: 小婷android | 来源:发表于2017-12-04 15:53 被阅读0次

在我们的开发中,很多时候为了避免多次创建同一个对象,而选择使用了单例模式,这样让我们节省了内存的消耗,对于开发是大有好处的。
最开始的时候,我写单例模式是这样的,代码如下:

public class Single {
    private static Single mSingle = null;

    public Single() {
    }

    public static Single getSingle() {
        if (mSingle == null) {
            mSingle = new Single();
        }
        return mSingle;
    }
}

这样的写法,针对单个线程是没有问题的,由于mSingle是静态的,所以可以保证每次运行的的时候只存在一个实例;但是对于多线程的开发就存在问题了,比如我有两个线程A、B,同时去访问getSingle()方法,这个时候会各自new出一个对象出来,这样就存在了两个实例,违背了单例模式的规则。然后我们可以将代码改进如下:

public class Single {
    private static Single mSingle = null;

    public Single() {
    }

    public static Single getSingle() {
        synchronized (Single.class) {
            if (mSingle == null) {
                mSingle = new Single();
            }
        }
        return mSingle;
    }

}

针对上述问题,我加了一个所机制,让他有序的去访问getSingle()方法,如果只是两三个线程的话,这样写是没有多大问题的,但是我们想一想,如果,在一个开发中有几百或者几千个线程呢?这样的话就存在一定的问题了,比如,首先是100个线程同时去抢mSingle的所有权,当一个线程抢到了,然后剩下的99个在继续这样抢,依此往下推,可能存在一个运气不好的,知道最后才抢到mSingle的所有权,那么客户端那边等待它返回的数据的时候就会过长,这对于开发者来说是不行的。
我们需要看一下上述代码,真的需要每次进入getInstance方法都要获得锁吗?其实不是的,整个Singleton类中,对mSingle进行访问的地方分为两类:读和写,而且仅当mSingle为null的时候才会写,mSingle一旦创建完毕,后面就只剩下读操作了,再怎么高并发也没什么关系了,反正mSingle已经是现成的,直接读就可以了。
所以,我们又可以对代码做如下修改:

public class Single {
    private static Single mSingle = null;

    public Single() {
    }

    public static Single getSingle() {
        if (mSingle == null) {
            synchronized (Single.class) {
                if (mSingle == null) {
                    mSingle = new Single();
                }
            }
        }
        return mSingle;
    }

}

最终,写下一种完全应用高并发的单例模式

public class Single {

    private Single() {
    }

    private static class InstanceHolder {
        private static final Single instance = new Single();
    }

    public static Single getInstance() {
        return InstanceHolder.instance;
    }

}

相关文章

网友评论

      本文标题:设计模式之单例模式

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