Java 单例模式探讨

1.预先加载法

 

Java代码  
  1. class S1 {   
  2.     private S1() {   
  3.         System.out.println("ok1");   
  4.     }   
  5.   
  6.   
  7.     private static final  S1 instance = new S1();   
  8.   
  9.     public static S1 getInstance() {   
  10.         return instance;   
  11.     }   
  12. }  

 

优点:  

1.线程安全的

2.在类加载的同时已经创建好一个静态对象,调用时反应速度快。

缺点: 资源利用效率不高,可能getInstance永远不会执行到,但是执行了该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化了

 

 

2.initialization on demand,延迟加载法  (考虑多线程)

 

Java代码  
  1. class S2 {   
  2.     private S2() {   
  3.         System.out.println("ok2");   
  4.     }   
  5.   
  6.     private static S2 instance = null;   
  7.   
  8.     public static synchronized S2 getInstance() {   
  9.         if (instance == null) instance = new S2();   
  10.         return instance;   
  11.     }   
  12. }  

 

优点: 资源利用率高,不执行getInstance就不会被实例,可以执行该类其他静态方法。


缺点: 第一次加载时发应不快  ,多线程使用不必要的同步开销大

 

3.initialization on demand double check 双重检测( 考虑多线程 )

 

Java代码  
  1. class S3 {   
  2.     private S3() {   
  3.         System.out.println("ok3");   
  4.     }   
  5.   
  6.     private static S3 instance = null;   
  7.   
  8.     public static S3 getInstance() {   
  9.         if (instance == null) {   
  10.             synchronized (S3.class) {   
  11.                 if (instance == null)   
  12.                     instance = new S3();   
  13.             }   
  14.         }   
  15.         return instance;   
  16.     }   
  17. }  

 

优点: 资源利用率高, 不执行getInstance就不会被实例,可以执行该类其他静态方法。


缺点: 第一次加载时发应不快  ,由于java 内存模型一些原因偶尔会失败

 

 

4.initialization on demand holder  (考虑多线程)

 

Java代码  
  1. class S4 {   
  2.     private S4() {   
  3.         System.out.println("ok4");   
  4.     }   
  5.   
  6.     private static class S4Holder {   
  7.        private static final  S4 instance = new S4();   
  8.     }   
  9.   
  10.   
  11.     public static S4 getInstance() {   
  12.         return S4Holder.instance;   
  13.     }   
  14. }  

 

优点: 资源利用率高, 不执行getInstance就不会被实例,可以执行该类其他静态方法。


缺点: 第一次加载时发应不快

 

 

 

总结: 一般采用 1 即可,若对资源十分在意或多线程也可考虑 4 ,不要使用2,3了。

猜你喜欢

转载自chenyajie.iteye.com/blog/1844791