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

蜂蜜果味儿糖

蜂蜜果味儿糖

2016-02-19 10:49

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

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

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

代码如下:

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. 不使用延迟实例化,而是用提前实例化。

即程序改写为:

代码如下:

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的开销不会特别大。是否还可以改进,看 下面。

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

代码如下:

public Class Singleton{
private volatile static Singleton instance;

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

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

}
return instance;
}
}

展开更多 50%)
分享

猜你喜欢

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

编程语言 网络编程
review引发的有关于单例模式的思考

关于设计趋势的思考

设计
关于设计趋势的思考

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

关于“智慧瑜伽”的思考

瑜伽 养生 健康
关于“智慧瑜伽”的思考

详细解析关于横屏模式的一些思考

平面设计 海报设计 广告设计 画报设计 签名设计 服装设计 名片设计 画册设计 版式设计 商标设计
详细解析关于横屏模式的一些思考

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Photoshop关于变形的思考

PS PS教程
Photoshop关于变形的思考

关于摄影构思的思考

摄影入门 摄影
关于摄影构思的思考

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Android中判断有无可用网络的代码(是否是3G或者WIFI网络)

Android中判断有无可用网络的代码(是否是3G或者WIFI网络)

关于实现代码语法标亮 dp.SyntaxHighlighter

关于实现代码语法标亮 dp.SyntaxHighlighter
下拉加载更多内容 ↓