国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

review引發(fā)的有關(guān)于單例模式的思考

2019-11-26 16:12:48
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

一次代碼調(diào)試中發(fā)現(xiàn)一個(gè)情況,即我在查看memcached的connection時(shí),發(fā)現(xiàn)總是維持在100來(lái)個(gè)左右,當(dāng)然這看似沒(méi)什么問(wèn)題,因?yàn)閙emcached默認(rèn)connection有1024個(gè)。但是我想的是為什么會(huì)有100來(lái)個(gè),因?yàn)槲业膍emcachedclient的產(chǎn)生采用的是單例模式我定義了一個(gè)memcachedClientFactory類,主要代碼如下:

復(fù)制代碼 代碼如下:

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;
}
}
}

回到最初的問(wèn)題,為什么會(huì)有100多個(gè)連接?

上面這個(gè)寫法真的能保證只產(chǎn)生一個(gè)連接?很顯然是不能,為什么?多線程并發(fā)!問(wèn)題就出在這里,當(dāng)有多個(gè)線程同時(shí)進(jìn)入createClient()方法時(shí),而且剛好都判斷為memcachedClient為null,這時(shí)候就產(chǎn)生了多個(gè)連接。哈,問(wèn)題找到了。

改進(jìn):

復(fù)制代碼 代碼如下:

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

這樣就ok了,改動(dòng)很簡(jiǎn)單。程序是沒(méi)有問(wèn)題了,而且也能保證只有一個(gè)連接。

不過(guò)拋開(kāi)這個(gè)問(wèn)題,我們可以繼續(xù)就如何解決單例模式下的并發(fā)問(wèn)題深入思考一下。

我總結(jié)一下,要解決單例模式在并發(fā)下的問(wèn)題,大概有三種方式:

1. 不使用延遲實(shí)例化,而是用提前實(shí)例化。

即程序改寫為:

復(fù)制代碼 代碼如下:

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

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

這樣做時(shí),jvm在加載類時(shí)就立馬創(chuàng)建了該實(shí)例,所以這樣做的前提是,創(chuàng)建該實(shí)例的負(fù)擔(dān)不大,我不比過(guò)多的考慮性能,并且我們確認(rèn)該實(shí)例是一定會(huì)用到的。其實(shí)我前面的代碼也完全可以使用這個(gè)方式:

復(fù)制代碼 代碼如下:

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;
}
}
}

不過(guò),看上去似乎沒(méi)有問(wèn)題,但是有隱患,即一旦有人不小心調(diào)用了memcachedClient.shutdown()方法,那整個(gè)程序就無(wú)法再生出新的memcachedClient了。當(dāng)然這是極端情況了,但是為了代碼的健壯,可以再改為:

復(fù)制代碼 代碼如下:

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

2.  就是使用synchronized關(guān)鍵字。

這么做可以保證同步問(wèn)題,但是我們知道使用synchronized的開(kāi)銷是很大的,會(huì)嚴(yán)重影響性能,所以用這個(gè)的前提是,你確認(rèn)不會(huì)經(jīng)常調(diào)用這個(gè)方法,或者你創(chuàng)建這個(gè)instance的開(kāi)銷不會(huì)特別大。是否還可以改進(jìn),看 下面。

3. 使用“雙重檢查加鎖“,在getInstance中見(jiàn)識(shí)使用同步

復(fù)制代碼 代碼如下:

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;
}
}

 

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 红河县| 玉山县| 巧家县| 合阳县| 台南市| 洛宁县| 文水县| 修文县| 航空| 阿拉善右旗| 东乡族自治县| 福建省| 九寨沟县| 赤城县| 凤山市| 贵德县| 弋阳县| 神木县| 宁明县| 浦北县| 苗栗市| 昌图县| 尼勒克县| 平顶山市| 三明市| 东阿县| 台中县| 奇台县| 牡丹江市| 竹溪县| 凤凰县| 定南县| 利辛县| 新和县| 昂仁县| 乐山市| 德令哈市| 龙胜| 牙克石市| 谢通门县| 中阳县|