单例模式
2016-02-24 15:19
239 查看
单例:即这个类只能有一个对象,
如果类的构造函数是公有的,那么就能创建多个对象,所以类的构造函数应该是私有的,随之而来的问题是,构造函数私有在类的外部还怎么创建对象,static帮我们解决了这个问题,
所以初步的单例我们写成这样
如果是多线程的情况,那么上面的代码是有问题的,假设有两个线程A,B线程A执行getInstance()方法,进去之后发现mTest==null,就会进入方法体内部,同时,线程B也执行到这个部分,发现mTest==null(此时线程A还没有执行mTest=newTest()),就会进入方法体内部,这就导致产生了连个对象实例,所以是有问题的。
解决办法:加同步
上面的代码虽然解决了多线程的问题,但是将代码块同步是非常耗的的一个操作,事实上,只有在mTest==null的时候才需要同步,mTest != null时是无法创建多个对象的
改进
如果类的构造函数是公有的,那么就能创建多个对象,所以类的构造函数应该是私有的,随之而来的问题是,构造函数私有在类的外部还怎么创建对象,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; } }
相关文章推荐
- java便捷开发
- DEDECMS自动编号(序号)autoindex属性
- qt自定义搜索框(超简单,带效果图)
- input子系统学习笔记二:数据结构
- Mongodb 重命名集合、列
- topK问题
- 适配ios设备集锦
- Git创建空白新分支
- getSupportFragmentManager()方法不可用解决办法
- FOR循环删除文件后缀名
- 【C++】低版本VS程序使用高版本打开的问题
- Hadoop基础之RPC机制以及HDFS源码分析
- linux下vi或vim操作Found a swap file by the name的原因及解决方法
- 选择排序与堆排序
- 分布式读写分离架构
- Spring-web源码解析之Filter-AbstractRequestLoggingFilter
- Brillo系统安装指导
- Log4j 配置最全说明
- 区分多态和重载
- 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(四)