按:本文为ATIP团内部培训笔记,主讲人:winters1224,记录人:hunterkathy,转载请注明出处;
一、单例模式的概念:
单例,即单一实例;
单例模式,保证整个系统的上下文中只有一个类的实例;
系统上下文:即ClassLoader;
第三方定义上下文:SpringIOC
二、单例模式的作用:
1、节约内存:内存中只保留一份和实例相关的资源
应用:如配置文件和缓存
2、控制多线程同步
任意多个线程,都只访问一个实例,天然的实现“写同步”
三、单例模式的实现:
方式1:
public class Single{
public static Single s;
private Single(){}
public static Single getInstance(){
if(s==null){
s=new Single();
}
return s;
}
}
分析:
方式1只适合单线程,当多个线程读进来,同时判断s==null时,将导致创建多个实例。
方式2:
public class Single{
public static Single s;
private Single(){}
public static synchronized Single getInstance(){
if(s==null){
s=new Single();
}
return s;
}
}
分析:
方式2的方法中增加了同步管理,多个线程之间,实现后进入者等待机制,满足了同步需求;
但是该实现中对整个方法加了同步锁,无需同步实现的操作也被加锁,存在性能问题;
另外,synchronized对环境要求苛刻,在特殊情况下将失效,如多cpu的情况。
方式3:
public class Single{
public static Single s;
private Single(){}
public static Single getInstance(){
if(s==null){
synchronized(s){
if(s==null){
s=new Single();
}
}
}
return s;
}
}
分析:
该实现为双重锁,即在方法中对class加锁。
注意,在锁内,实例可被重新初始化,所以对实例加锁无意义。
方式4:
public class Single{
public static final Single s=new Single();
private Single(){}
}
分析:
要保证两点:1、构造方法私有化――封装构造方法的可见性;2、实例是静态的: static (final);
方式5:
public Enum Single{
S;
private Single(){}
}
分析:
使用枚举来实现单例,避免多线程同步问题,以及绝对避免多次实例化问题;
四、注意点:
在多线程环境下,要注意考虑同步问题:1、如何实现 2、写单例
五、模式协作:
1、配合工厂模式:提供实例
2、配合亨元模式:copy机制,复用一个提供的实例
如:数据库连接池的应用,菜单树的应用
3、配合MVC模式:如servlet
六、项目应用:
public class PrecastMethodFactory {
/**
* 空白公式和公式法,这个公式可以用单例。
* <p>
* 2013年10月12日 团长 增加公式法的单例
*
* @author �F�L
* @since 2013-9-9
*/
private static final PremethodModel METHOD_BLANK = new BlankFormulaMethodModel(),
METHOD_FMLA = new FormulaMethodModle();
……
}
Spring IOC:
<bean id="BaseDBService"
class="com.sinosig.evaluation.base.service.impl.DefaultBaseDBServiceImpl">
<property name="dao" ref="BaseMybatisDao" />
<property name="batchDao" ref="BaseMybatisDao" />
</bean>
注:未定义scope的,默认都是SpringIOC的单例(不是指ClassLoader的);
七、单例模式总结:
1、保证上下文中只有一个单例
2、节约内存
3、实现方式要点:封装构造方法的可见性
4、注意事项:多线程操作
5、与其它模式协作:工厂模式,亨元模式,mvc模式等
6、项目应用:部分预测方法