review引发的有关于单例模式的思考
MemcachedClientFactory{
privateMemcachedConnectionBuildermemcachedConnectionBuilder;
privateStringservers;
privatestaticMemcachedClientmemcachedClient;
privateMemcachedClientFactory(){
}
privateMemcachedClientFactory(MemcachedConnectionBuildermemcachedConnectionBuilder,Stringservers){
this.memcachedConnectionBuilder=memcachedConnectionBuilder;
this.servers=servers;
}
publicstaticMemcachedClientcreateClient(){
if(memcachedClient==null){
this.memcahcedClien=newMemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
returnthis.memcahcedClient;
}
}
}
上面这个写法真的能保证只产生一个连接?很显然是不能,为什么?多线程并发!问题就出在这里,当有多个线程同时进入createClient()方法时,而且刚好都判断为memcachedClient为null,这时候就产生了多个连接。哈,问题找到了。
改进:
publicstaticsynchronizdMemcachedClientcreateClient(){
if(memcachedClient==null){
this.memcahcedClien= new
MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
returnthis.memcahcedClient;
}
这样就ok了,改动很简单。程序是没有问题了,而且也能保证只有一个连接。
不过抛开这个问题,我们可以继续就如何解决单例模式下的并发问题深入思考一下。
我总结一下,要解决单例模式在并发下的问题,大概有三种方式:
即程序改写为:
publicstaticSingletongetInstance(){ privateMemcachedClientFactory(){ privateMemcachedClientFactory(MemcachedConnectionBuildermemcachedConnectionBuilder,Stringservers){ publicstaticMemcachedClientcreateClient(){ 不过,看上去似乎没有问题,但是有隐患,即一旦有人不小心调用了memcachedClient.shutdown()方法,那整个程序就无法再生出新的memcachedClient了。当然这是极端情况了,但是为了代码的健壮,可以再改为: 2. 就是使用synchronized关键字。 这么做可以保证同步问题,但是我们知道使用synchronized的开销是很大的,会严重影响性能,所以用这个的前提是,你确认不会经常调用这个方法,或者你创建这个instance的开销不会特别大。是否还可以改进,看下面。 privateSingleton(){}; }
PublicClassSingleton{
privatestaticSingletoninstance=newSingleton();
privateSingleton(){};
returninstance;
}
}
MemcachedClientFactory{
privateMemcachedConnectionBuildermemcachedConnectionBuilder;
privateStringservers;
privatestaticMemcachedClientmemcachedClien=new
MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
this.memcachedConnectionBuilder=memcachedConnectionBuilder;
this.servers=servers;
}
returnthis.memcahcedClient;
}
}
}
publicstaticMemcachedClientcreateClient(){
if(memcachedClient==null){
this.memcahcedClien=newMemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
returnthis.memcahcedClient;
}
publicClassSingleton{
privatevolatilestaticSingletoninstance;
publicstaticSingletongetInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=newSingleton();
}
}
returninstance;
}
}相关文章