简述
关于单例模式早已经是老生常谈,在应聘过程中,也多次被问及,很多都是关于性能的问题。
优点
单例,由于只有一个实例,减少了内存开销,作为系统的全局访问点,优化了资源访问。
实现
在实现过程中,一般为饿汉和懒汉模式两种
饿汉模式最简单,所谓饿了就吃,所以,在饿汉模式中,单例实例是在定义的时候,就已经加载的,像这样 :
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){
}
public static getInstance(){
return instance;
}
//其他的方法...
}
饿汉模式是线程安全的,因为虚拟机只会装载一次,在装载类的时候不会发生并发的。
懒汉模式,说到懒,那么,java开发者首先会想到Hibernate的懒加载机制(有些人还会想到自己碰到的一些坑,hibernate映射的时候,使用了一个还没有初始化的其他类的对象,只能用懒加载机制解决,还记得那个报错吗?(^$^))
这里以双重检查加锁为例,代码如下
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
//其他的方法...
}
显然,这种方法减少了每次访问都要进行同步的问题,一旦实例化后,就可以并行访问了,减少串行的效率问题,但是这里还是有判断if的开销,
在《研磨设计模式》一书中,谈到了Lazy initialization holder class模式,使用了 [java的类级内部类和多线程缺省同步锁机制],详细代码如下:
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static getInstance(){
return SingletonHolder.instance;
}
private static class SingletonHolder{
/*
*静态初始化器,由JVM来保证线程安全
*/
private static Singleton instance = new Singleton();
}
//其他的方法...
}
在《研磨设计模式》一书中,还谈到了使用枚举的方法,代码如下:
public enum Singleton{
/*
*定义一个枚举的元素,它就代表了Singleton的一个实例
*/
uniqieInstance;
/*
*定义的其他方法
*/
public void singletonOperation(){
......
}
.....
}
使用枚举类来实现单例,更加简洁,而且包含无偿的序列化机制,并由JVM从根本上提供保障,防止多次实例化,简洁 、高效 、 安全。
关于enum的实践:O溺水的鱼0
单例模式与垃圾回收:用心真诚
No Final is final