创建模式之单例模式
在面试时经常会有人问单例模式,单例模式是在整个系统运行中仅且仅有一个实例,在被调用。我们熟知的Calendar就是这种,
Calendar.newInstance()获取实例。此时,构造器要设置为private,防止被new实例。连接池也是整个系统仅有一个,采用单例模式,但连接池中的每条连接却采用原型模式创建。
单例模式因被整个系统运行,因此不能存在可被修改的实例变量。另外SpringMvc中的Controller和Service都为单例模式。
而Struts中的Controller为原型模式。
1.单例模式-饿汉加载
饿汉模式:在系统创建,启动时创建对象。由于静态变量的声明在编译时已经明确,因此在系统装载时就已经产生。不牵涉线程安全问题。
1 public class SingletonModel { 2 3 private static final SingletonModel singleton = new SingletonModel(); 4 5 /** 6 * 私有化构造实例 7 */ 8 private SingletonModel(){ 9 } 10 11 public static SingletonModel newInstance(){ 12 return singleton; 13 } 14 }
采用静态代码段方式
1 private static SingletonModel singleton = null; 2 static{ 3 singleton = new SingletonModel(); 4 }
2.单例模式-懒汉加载
懒汉模式:在第一次被调用的时候创建。
1 public class SingletonModel { 2 3 private static SingletonModel singleton = null; 4 5 /** 6 * 私有化构造实例 7 */ 8 private SingletonModel(){ 9 } 10 11 public static SingletonModel newInstance(){ 12 if(singleton == null){ 13 singleton = new SingletonModel(); 14 } 15 return singleton; 16 } 17 }
2.1 因用newInstance的方式,不适合多线程,而如果给newInstance方法加 synchronized同步锁(如示例1),但是同步又牵扯到性能,如果每一个线程都先做这个操作,就没有必要。
2.2 给代码块添加同步锁(如示例2),这种情况又会牵扯一个问题,就是A线程判断instance为null时,B线程也判断出instance为null,此时A单线程处理,B在等待,A创建对象完后,同步锁释放,B因为已经进入instance为null的里面,因此也会创建对象。为此需要进行双验证,即双保险。(如示例3)
1 public static synchronized SingletonModel newInstance(){
1 public static SingletonModel newInstance(){ 2 if(singleton == null){ 3 synchronized(SingletonModel.class){ 4 singleton = new SingletonModel(); 5 } 6 } 7 return singleton; 8 }
1 public static SingletonModel newInstance(){ 2 if(singleton == null){ 3 synchronized(SingletonModel.class){ 4 if(singleton == null){ 5 singleton = new SingletonModel(); 6 } 7 } 8 } 9 return singleton; 10 }
参考文摘:
( java设计模式学习系列之一:单例模式(Singleton))http://blog.csdn.net/qjyong/article/details/1721342
(五种方法实现Java的Singleton单例模式)http://www.cnblogs.com/pkufork/p/java_singleton.html
------------------------------------------------------------------------------------------------------------------------------
如有纰漏之处,还望指正。
---DennyZhao