单例模式

77 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

单例模式类只有一个实例。类通过构造器私有化不允许在外部实例化类对象。

饿汉模式

不管是否使用,一上来就初始化对象。由于是在加载时创建,是线程安全的。

public class Singleton {  
     private static Singleton instance = new Singleton();  
     private Singleton (){
     }
     public static Singleton getInstance() {  
     return instance;  
     }  
 }  

懒汉模式

在需要使用时才创建对象。由于可能存在线程争抢,是线程不安全的。

public class Singleton {  
      private static Singleton instance;  
      private Singleton (){
      }   
      public static Singleton getInstance() {  
      if (instance == null) {  
          instance = new Singleton();  
      }  
      return instance;  
      }  
 }  

懒汉加锁

在创建对象的时候加synchronized保证线程安全

缺点:在对象创建以后是不需要synchronized的,导致效率降低。

public class Singleton {  
      private static Singleton instance;  
      private Singleton (){
      }
      public static synchronized Singleton getInstance() {  
      if (instance == null) {  
          instance = new Singleton();  
      }  
      return instance;  
      }  
 }  

双重判断

使用volatile保证内存可见性,只在创建对象的时候加锁synchronized

public class Singleton {  
      private volatile static Singleton instance;  
      private Singleton (){
      }   
      public static Singleton getInstance() {  
      if (instance== null) {  
          synchronized (Singleton.class) {  
          if (instance== null) {  
              instance= new Singleton();  
          }  
         }  
     }  
     return singleton;  
     }  
 }  

静态内部类

原理:只在获取对象的时候才会加载内部类,类加载是线程安全的。

第一次加载Singleton类时并不会初始化sInstance,只有第一次调用getInstance方法时虚拟机加载SingletonHolder 并初始化sInstance ,这样不仅能确保线程安全也能保证Singleton类的唯一性。

public class Singleton { 
    private Singleton(){
    }
      public static Singleton getInstance(){  
        return SingletonHolder.sInstance;  
    }  
    private static class SingletonHolder {  
        private static final Singleton sInstance = new Singleton();  
    }  
} 

spring中的单例

spring容器中的bean默认已单例方式存在。spring容器中的对象在BeanFactory创建以后存在缓存中,获取对象实例的时候直接从缓存中获取,并注入到其他对象中。

// 部分逻辑代码
public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{    
   /**  
    * 单例对象缓存map
    */    
   private final Map singletonCache=new HashMap();    
   public Object getBean(String name)throws BeansException{    
       return getBean(name,null,null);    
   }    
   public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{    
 
      //synchronized 保证线程安全   
      synchronized(this.singletonCache){    
         sharedInstance=this.singletonCache.get(beanName);    
       }    
      if(sharedInstance!=null){    
         //返回缓存Bean实例    
         bean=getObjectForSharedInstance(name,sharedInstance);    
      }else{     
        RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);   
        if(mergedBeanDefinition.isSingleton()){    
           synchronized(this.singletonCache){      
             sharedInstance=this.singletonCache.get(beanName);    
             if(sharedInstance==null){    
               try {    
                  //创建Bean实例    
                  sharedInstance=createBean(beanName,mergedBeanDefinition,args);    
                  //添加到缓存
                   addSingleton(beanName,sharedInstance);    
               }catch (Exception ex) {    
               }finally{    
              }    
             }    
           }    
          bean=getObjectForSharedInstance(name,sharedInstance);    
        }    
}    
   return bean;    
}    
}

单例模式是最简单、最常用的设计模式。