您的位置:首页 > 其它

单例模式

2016-02-24 15:19 239 查看
单例:即这个类只能有一个对象,

如果类的构造函数是公有的,那么就能创建多个对象,所以类的构造函数应该是私有的,随之而来的问题是,构造函数私有在类的外部还怎么创建对象,static帮我们解决了这个问题,

所以初步的单例我们写成这样

class Test{
private Test mTest;
private Test(){//将构造函数声明为私有的,只有类的内部才能构造对象
}

public static Test getInstance(){
if (mTest == null){
//mTest为空,表示还没有创建对象,我们就利用私有构造方法创建对象,如果我们不需要这个实例,它就永远不会产生,这叫延迟实例化
mTest = new Test();
}
return mTest;
}
}


如果是多线程的情况,那么上面的代码是有问题的,假设有两个线程A,B线程A执行getInstance()方法,进去之后发现mTest==null,就会进入方法体内部,同时,线程B也执行到这个部分,发现mTest==null(此时线程A还没有执行mTest=newTest()),就会进入方法体内部,这就导致产生了连个对象实例,所以是有问题的。

解决办法:加同步

class Test{
private Test mTest;
private Test(){
}

public static synchronized Test getInstance(){
//加synchronized的作用是,只有正在执行该方法的线程执行完成之后,其它线程才能执行该方法,就像排队取款一样,只有前面的人取完之后,其它人才能取
if (mTest == null){
mTest = new Test();
}
return mTest;
}
}


上面的代码虽然解决了多线程的问题,但是将代码块同步是非常耗的的一个操作,事实上,只有在mTest==null的时候才需要同步,mTest != null时是无法创建多个对象的

改进

class Test{
private Test mTest;
private Test(){
}

public static Test getInstance(){

if (mTest == null){ //对象没有创建的时候才需要执行同步代码块执行同步的代码创建对象
synchronized(Test.class){
if (mTest == null){//有两个线程同A,B时进入了第一个if语句内部,接着执行同步代码块,A线程A执行完了同步代码块创建了对象出来了,线程B又进入了同步代码块,如果没有第二个if语句,那么线程B也会创建一个对象,这就不叫单例了
mTest = new Test();
}
}

}
return mTest;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: