时间:2021-05-19
一次代码调试中发现一个情况,即我在查看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.不使用延迟实例化,而是用提前实例化。
即程序改写为:
复制代码 代码如下:
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;
private Singleton(){};
public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
单例模式Singleton简单实例设计模式解析前言今天我来全面总结一下Android开发中最常用的设计模式-单例模式。关于设计模式的介绍,可以看下我之前写的:1
本文主要介绍了关于单例模式的一些问题,想学习C#单例模式的同学们可以看一看,还是有些帮助c#中的单例模式单例模式是指在设计一个类时,保证在运行期间只有一个实例对
java单例模式的实例详解概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。 单例模式有一下特点:
单例模式概念:java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。单例模式有一下特点:1、单例类只能有一个实例。2、
前言大家都知道关于Java中单例(Singleton)模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器