单例模式

来源:互联网 发布:2017神优化单机游戏 编辑:程序博客网 时间:2024/06/01 09:30
  1. package lock;  
  2.   
  3. public class EhanSingleton {  
  4.       
  5.     /*饿汉加载模式/立即加载模式*/  
  6.       
  7.       
  8.     //初始化构造函数  
  9.     private  EhanSingleton(){  
  10.           
  11.     }  
  12.     private  static EhanSingleton  ehan = new EhanSingleton();  
  13.       
  14.     public static  EhanSingleton getInstance(){  
  15.         try {  
  16.             Thread.sleep(3000);   //方便多线程测试  
  17.         } catch (InterruptedException e) {  
  18.             e.printStackTrace();  
  19.         }  
  20.           return  ehan ;  
  21.     }  
  22.   
  23. }  

     创建多个线程来测试一下

[java] view plain copy
  1. package lock;  
  2.   
  3. public class MyThread  extends  Thread{  
  4.          
  5.      @Override  
  6.     public void run() {  
  7.              System.out.println(EhanSingleton.getInstance());  
  8.            
  9.     }  
  10.      public static void main(String[] args) {  
  11.             MyThread m1 = new MyThread();  
  12.             MyThread m12 = new MyThread();  
  13.             MyThread m13 = new MyThread();  
  14.               
  15.             m1.start();  
  16.             m12.start();  
  17.             m13.start();  
  18.     }  
  19. }  
测试结果为:

cn.spring.dxcDanli.Singleton@132965a8
cn.spring.dxcDanli.Singleton@132965a8
cn.spring.dxcDanli.Singleton@132965a8

显示为三个相同的内存地址,说明这个模式符合单例


第二种为懒汉模式

[java] view plain copy
  1. package lock;  
  2.   
  3. public class LanHanSingleton {  
  4.       
  5.     /*懒汉模式/延迟加载*/  
  6.       
  7.     //私有化构造函数  
  8.     private LanHanSingleton(){  
  9.           
  10.     }  
  11.       
  12.     private  static LanHanSingleton lanHanSingleton ;   
  13.       
  14.     public  static  LanHanSingleton  getInstance() {  
  15.            if(lanHanSingleton == null){  
  16.                 try {  
  17.                     Thread.sleep(3000);  
  18.                      lanHanSingleton = new LanHanSingleton() ;  
  19.                 } catch (InterruptedException e) {  
  20.                     e.printStackTrace();  
  21.                 }  
  22.                 
  23.            }  
  24.           return lanHanSingleton ;    
  25.     }  
  26.   
  27. }  
用多线程去测试一下是否每个对象的HashCode的值是保持一致的

[java] view plain copy
  1. package lock;  
  2.   
  3. public class MyThread  extends  Thread{  
  4.          
  5.      @Override  
  6.     public void run() {  
  7.              System.out.println(LanHanSingleton.getInstance().hashCode());  
  8.            
  9.     }  
  10.      public static void main(String[] args) {  
  11.             MyThread m1 = new MyThread();  
  12.             MyThread m12 = new MyThread();  
  13.             MyThread m13 = new MyThread();  
  14.               
  15.             m1.start();  
  16.             m12.start();  
  17.             m13.start();  
  18.     }  
  19. }  

测试结果如下:

126720696
137014984
1638443495

测试的结果发现 这个已经不符合单例模式,他们并不是同一个对象了,而是几个不同的对象,所以这种懒汉模式在单线程中是符合单例模式的,不过在多线程环境中是不符合单例模式

 

synchrinized关键字,来看看效果

[java] view plain copy
  1. package lock;  
  2.   
  3. public class LanHanSingleton {  
  4.       
  5.     /*懒汉模式/延迟加载*/  
  6.       
  7.     //私有化构造函数  
  8.     private LanHanSingleton(){  
  9.           
  10.     }  
  11.       
  12.     private  static LanHanSingleton lanHanSingleton ;   
  13.       
  14.     public synchronized  static  LanHanSingleton  getInstance() {  
  15.            if(lanHanSingleton == null){  
  16.                 try {  
  17.                     Thread.sleep(3000);  
  18.                      lanHanSingleton = new LanHanSingleton() ;  
  19.                 } catch (InterruptedException e) {  
  20.                     e.printStackTrace();  
  21.                 }  
  22.                 
  23.            }  
  24.           return lanHanSingleton ;    
  25.     }  
  26.   
  27. }  
测试结果如下

1638443495
1638443495
1638443495

大家发现这样的确可以解决多线程带来的不同对象所导致的问题,但是这个方法并不好,这种方法效率非常低下,一定要等到上一个线程释放锁以后才能获取对象

同步方法是对整个方法持有锁,这个对于效率来说实在太慢,大家还会想到用同步块,那么我们在试一试

[java] view plain copy
  1. <span style="font-size:14px;">package lock;  
  2.   
  3. public class LanHanSingleton {  
  4.       
  5.     /*懒汉模式/延迟加载*/  
  6.       
  7.     //私有化构造函数  
  8.     private LanHanSingleton(){  
  9.           
  10.     }  
  11.       
  12.     private  static LanHanSingleton lanHanSingleton ;   
  13.       
  14.     public   static  LanHanSingleton  getInstance() {  
  15.            try {  
  16.              synchronized (LanHanSingleton.class) {  
  17.                  if(lanHanSingleton == null){  
  18.                         Thread.sleep(3000);  
  19.                          lanHanSingleton = new LanHanSingleton() ;  
  20.                }  
  21.             }     
  22.             
  23.                 } catch (InterruptedException e) {  
  24.                     e.printStackTrace();  
  25.                 }  
  26.                 
  27.           return lanHanSingleton ;    
  28.     }  
  29.   
  30. }</span>  

其实这个效果和上个效果差不多,效率都是比较慢的,和同步方法synchronized一样是同步运行的

这里最好的方式就是DCL双检查锁机制,也就是同步代码块

[java] view plain copy
  1. package lock;  
  2.   
  3. public class LanHanSingleton {  
  4.       
  5.     /*懒汉模式/延迟加载*/  
  6.       
  7.     //私有化构造函数  
  8.     private LanHanSingleton(){  
  9.           
  10.     }  
  11.       
  12.     private  static LanHanSingleton lanHanSingleton ;   
  13.       
  14.     public   static  LanHanSingleton  getInstance() {  
  15.            try {  
  16.               
  17.                  if(lanHanSingleton == null){  
  18.                      synchronized (LanHanSingleton.class) {  
  19.                          if(lanHanSingleton == null){  
  20.                              lanHanSingleton = new LanHanSingleton() ;  
  21.                          }  
  22.                           
  23.                      }  
  24.                }  
  25.             
  26.                 } catch (InterruptedException e) {  
  27.                     e.printStackTrace();  
  28.                 }  
  29.                 
  30.           return lanHanSingleton ;    
  31.     }  
  32.   
  33. }  



原创粉丝点击