1.单例模式【Singleton Pattern】:
方法一:
Public class A{
Private static A a = null;
Private A(){
}
Public static A getInstance(){
If (a == null){
This.a = new A();
}
return a;
}
}
方法2:
Public class A{
//直接new一个实例传给成员变量,别人要的时候通过getInstance()直接传递给你
Private static final A a = new A();
Private A(){
}
Public synchronized static A getInstance(){
return a;
}
}
2.单例模式的实现过程:
1.定义一个这个A类类型的静态变量 a,private static A a = null;
2.private + 类名的构造函数,必须是私有的,是保证这个类不能被其它类new出来。
Private A{}
3.对外提供一个一个public static A getInstance()的方法,其它类只能通过这个方法来得到这个类A的实例
3. 方法一和方法二的比较:
方法二比方法一更加通用,更加完美,为什么呢?
因为方法一存在风险,方法一是线程不安全的,在一个B/S项目中,每个HTTP Request请求到J2EE的容器后就创建了一个线程,每个线程创建一个单例对象怎么办?假设这时候我们用方法一,大家看黄色部分,假如这会儿有两个线程A,B, 线程A执行到This.a = new A();在堆上正在申请内存空间,可能需要0.001微秒,就在这0.001微秒之内,线程B执行到 If (a == null),你说这个判断条件是true还是false呢?是true,因为线程A在堆上正在分配内存空间,还没有创建出实例来。那么,线程B也往下走,内存中就有两个a实例了,看看是不是出问题了?如果你这个单例是去拿一个序列号或者创建一个信号资源的时候,会怎么样?业务逻辑混乱!
数据一致性校验失败!最重要的是你从代码上还看不出什么问题,这才是最要命的!因为这种情况基本上你是重现不了的,不寒而栗吧,那怎么修改?用方法二,方法而通过final和synchronized 两个关键字解决了以上假设的问题!synchronized 用来解决线程不安全的问题。
4. 单例模式的优缺点:
优点:
1.减少了内存的开支,特别是一个对象需要频繁的创建、销毁时,而且创建和销毁的性能又无法优化,单利模式的优势就非常明显。
2.减少了系统的性能开销,当一个对象的产生需要比较多的资源的时候,如读取配置、产生其它依赖对象时,则可以在应用启动时直接产生一个单例对象,然后永久驻留在内存的方式来解决(在java EE采用单例模式时需要注意JVM垃圾回收机制)
缺点:1..单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。
2.单例模式对测试是不利的。
5. 最佳实践:
单例模式应用非常广泛,如在Spring中,每个Bean默认就是单例singleton的,这样做的优点是Spring容器可以管理这些bean的生命周期,决定什么时候创建出来,什么时候销毁,销毁的时候如何处理,如果采用非单例模式(Prototype),则bean初始化的管理交由J2EE容器,Spring容器不在跟踪管理Bean的生命周期。(自己也在学Spring中用过)