再论单例模式

工作也有一年多的时间了,这一年有喜也有忧,不过不管怎么说换了工作换了环境就得好好干,新的开始新的天地!呵呵。。。

旧的一年里技术上没有什么大的长进,就设计模式来说吧,工作中用到过但是始终不知道不理解 到底是怎么回事,管理以及团队配合上是学习不少,这都要感谢我去年的头(说实在的真的很佩服他!)

现在有了些时间好好地回顾了一下,在此就把自己的理解以作为备忘,同时也希望能帮助其他的人。好了不多说了,直接说单例吧!


public class Singleton {
	
	private Singleton instance = null;
	private Singleton(){}
	public Singleton getIntance(){
		if(instance == null){
			instance = new Singleton();
		}
		return instance;
	}

}




可以看到上面这就是一个简单的单例,和我们日常用到的其他类相比 单例的标准我们看到
了,他的 构造函数 必须是私有的(不然的话外界引用的时候就可以实例化了) 其次 我们要提供一个能实例化自身并且返回给调用者的这样一个方法!

可以看到上面的这个实例很简单,但是问题出现了如果我们加入了线程怎么办?

比如现在我们有一个需求需要一边读log一边写 怎么办? log当然是个单例了。。。。

这个时候问题出现了。。如果读写可能要发生冲突了怎么办?

当然是使用线程同步了。。

伪代码如下:
public class Singleton {
	
	private Singleton instance = null;
	private Singleton(){}
	public Singleton synchronized getInstance(){
		if(instance == null){
			instance = new Singleton();
		}
		return instance;
	}

}


呵呵问题解决了,但是似乎隐藏的问题 被你看到了!的确,性能的确有问题,
但是 我们该如何来改进呢?

下面给出方案

第一种解决性能问题的方案:就是尽量减少你程序中使用该类的getInstance()方法
当然了 这绝对不是最优的方法

第二种解决方案:使用急切式的方法(前提是应用程序 频繁的使用或者创建单例,或者创建和运行时的负担不重)
     public class Singleton{
        private static Singleton uniqueInstance = new Singleton();
        private Singleton(){}
        public static Singleton getInstance(){
            return uniqueInstance;
        }
     }


第三种解决方案:
   使用双重检查锁(DCL)的形式:
     public class Singleton{
       private volatile static Singleton uniqueInstance;
       private Singleton(){}
       public static Singleton getInstance(){
            if(uniqueInstance == null){
                synchronized(Singleton.class){
                    if(uniqueInstance == null){
                        uniqueInstance = new Singleton();
                     }
                }
            }
       }
     }


第三种方案只有在第一次创建的时候才会同步,这样的话我们的性能相比较之前的会有很大的提升。

虽然给出了这三种方案,但是我还是有疑惑的地方比如在 第一种和第二种解决方案上面 我有些问题

可以看到 如果我们担心性能问题 那么就不能使用同步了,那么是不是同步问题和性能兼容上面我们只能选择第三种解决方案呢?希望哪位前辈 能再详细的解释一下啊!

猜你喜欢

转载自whao189.iteye.com/blog/1065903