review引发的有关于单例模式的思考

2016-02-19 10:49 3 1 收藏

生活已是百般艰难,为何不努力一点。下面图老师就给大家分享review引发的有关于单例模式的思考,希望可以让热爱学习的朋友们体会到设计的小小的乐趣。

【 tulaoshi.com - 编程语言 】

一次代码调试中发现一个情况,即我在查看memcached的connection时,发现总是维持在100来个左右,当然这看似没什么问题,因为memcached默认connection有1024个。但是我想的是为什么会有100来个,因为我的memcachedclient的产生采用的是单例模式我定义了一个memcachedClientFactory类,主要代码如下:

代码如下:

MemcachedClientFactory{
private MemcachedConnectionBuilder memcachedConnectionBuilder;
private String servers;
private static MemcachedClient memcachedClient;

private MemcachedClientFactory(){
}

private MemcachedClientFactory(MemcachedConnectionBuilder memcachedConnectionBuilder, String servers){
 this. memcachedConnectionBuilder= memcachedConnectionBuilder;
 this.servers=servers;
 }

public static MemcachedClient createClient(){
if(memcachedClient==null){
this.memcahcedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
 return this.memcahcedClient;
}
}
}

回到最初的问题,为什么会有100多个连接?

上面这个写法真的能保证只产生一个连接?很显然是不能,为什么?多线程并发!问题就出在这里,当有多个线程同时进入createClient()方法时,而且刚好都判断为memcachedClient为null,这时候就产生了多个连接。哈,问题找到了。

改进:

代码如下:

public static synchronizd MemcachedClient createClient(){
 if(memcachedClient==null){
this.memcahcedClien=  new
MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
 return this.memcahcedClient;
}

这样就ok了,改动很简单。程序是没有问题了,而且也能保证只有一个连接。

不过抛开这个问题,我们可以继续就如何解决单例模式下的并发问题深入思考一下。

我总结一下,要解决单例模式在并发下的问题,大概有三种方式:

1. 不使用延迟实例化,而是用提前实例化。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

即程序改写为:

代码如下:

Public Class Singleton{
private static Singleton instance=new Singleton();
private Singleton(){};

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

这样做时,jvm在加载类时就立马创建了该实例,所以这样做的前提是,创建该实例的负担不大,我不比过多的考虑性能,并且我们确认该实例是一定会用到的。其实我前面的代码也完全可以使用这个方式:

代码如下:

MemcachedClientFactory{
private MemcachedConnectionBuilder memcachedConnectionBuilder;
private String servers;
private static MemcachedClient memcachedClien= new
MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));

private MemcachedClientFactory(){
}

private MemcachedClientFactory(MemcachedConnectionBuilder memcachedConnectionBuilder, String servers){
 this. memcachedConnectionBuilder= memcachedConnectionBuilder;
 this.servers=servers;
 }

public static MemcachedClient createClient(){
 return this.memcahcedClient;
}
}
}

不过,看上去似乎没有问题,但是有隐患,即一旦有人不小心调用了memcachedClient.shutdown()方法,那整个程序就无法再生出新的memcachedClient了。当然这是极端情况了,但是为了代码的健壮,可以再改为:

代码如下:

public static MemcachedClient createClient(){
if(memcachedClient==null){
this.memcahcedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
return this.memcahcedClient;
}

2.  就是使用synchronized关键字。

这么做可以保证同步问题,但是我们知道使用synchronized的开销是很大的,会严重影响性能,所以用这个的前提是,你确认不会经常调用这个方法,或者你创建这个instance的开销不会特别大。是否还可以改进,看 下面。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

3. 使用“双重检查加锁“,在getInstance中见识使用同步

代码如下:

public Class Singleton{
private volatile static Singleton instance;

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

}
return instance;
}
}

来源:http://www.tulaoshi.com/n/20160219/1595858.html

延伸阅读
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动治理栈和堆,程序员不能直接地设置栈或堆。 !-- frame contents -- !-- /frame contents -- 2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,...
介绍 很多有着不同开发背景得人都会比较熟悉单例模式。他们会发现每次他们要创建一个不同的单例类的时候,都不得不写同样得代码。使用新的C# 2.0的泛型,可以实现只写一次同样得代码。 使用 C# 2.0 泛型来完成单例模式的重用 使用 C# 2.0 的泛型,使得实现我所说的"单例提供者"成为可能。这是一个可用来创建单例...
单例模式定义 : Ensure a class has only one instance, and provide a global point of access to it. 动态确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。     如上图所示(截取自《Head First Design Patterns》一书)。 通过使用private的构造函数确保了在一个应用中产生一个实例,并且是...
标签: Web开发
字体的处理在网页设计中无论怎么强调也不为过,毕竟网页使用来传递信息的,而最经典最直接的信息传递方式就是文字,所以,了解一点字体的基本知识对于设计来说还是非常重要的。 中文和英文的最大区别就是中文是方块字,英文是拼音文字,这对字体的处理的影响是巨大的。看看下面的图示就会发现,英文字体里的那些变化在中文字体里都弱...
有些不含活性菌的产品也会在标签上生成含有益生菌,或者标注的益生菌含量比实际要高。2013年,独立调查机构所做的调查发现19种益生菌营养品中,有5种实际含有的微生物比声称的要少。有些产品的益生菌含量仅有成分表上的56%,最少的只有表上声称的16%。 有关于益生菌的几个认识误区 有关于益生菌的几个认识误区 食物和营...

经验教程

189

收藏

28
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部