Loading

几种单例模式解析

1)单例模式的定义:

在整个应用中,保证一个类只有一个实例,它提供了一个可以访问到它自己的全局访问点(静态方法)。

 

2)单例模式的优缺点:

  优点:

  1、提供了对唯一实例的受控访问;

  2、Java中频繁创建和销毁类对象都会占用一部分系统资源,使用单例模式可以提高性能;

  3、允许可变数量的实例;

  缺点:

  1、单例模式中,没有抽象层,所以对于单例类的扩展并不方便;

  2、单例类的职责过重,在一定程度上违背了“单一职责原则”;

  3、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失;

3)简单介绍几种单例,单例模式中有区分了懒汉式和饿汉式,懒汉式主要是用时间来换空间,饿汉式则是用空间来换时间。饿汉式是线程安全的,懒汉式是非线程安全的,如果要实现懒汉式的非线程安全,则可以再访问点添加synchronized关键字声明即可。在其他的一些项目中还使用了双重检测枷锁机制。

  1、懒汉单例,存在线程不安全问题,如启动多线程,同时调用入口方法获取实例时不能正常工作:

//懒汉单例,线程不安全,当启动多线程,同时获取多个实例时会报错
   private static PostContentForResponse instance = null;
   private PostContentForResponse() {}
   public static PostContentForResponse getInstance() {
        if(instance == null) {
            instance = new PostContentForResponse();
        }
        return instance;
   }    

    懒汉模式也提供一种解决同步调用时不能正常工作的方法,使用synchronized声明访问点,但是工作效率低

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

   2、饿汉单例,这种方式基于classloder机制避免了多线程的同步问题,但是instance在类装载时就实例化,虽然导致类装载的原因有很多种,

    在单例模式中大多数都是调用getInstance方法,但是也不能确定有其他的方法(或者其他静态方法)导致类装载,这是初始化的instance

    显然没有达到lazy loading的效果。  

  private static PostContentForResponse instance = new PostContentForResonse();
 private PostContentForResponse() {}
 public static PostContentForResponse getInstance() {
     return instance;   
  }

   3、静态内部类,跟饿汉模式有点类似,只是在类装载的时候,SingletonHolder并没有被主动使用,只有显式调用getInstance方法是,才会调用装载SingletoHolder类,从而实例化instance,既实现了线程安全,又避免了同步带来的性能影响。

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

 3)  理解单例注入和@Component注入在Spring管理的Bean对象构建流程:
对于一个单例类@Autowired注解方式添加,启动时会报空指针异常,因为static类对象是创建对象后,内存中还没有注入Bean信息,而且无法初始化Bean实例。
解决方法:例如@PostConstruct来对单例类中对象注入:

@Component
public class RestTemplateUtil {
    public static RestTemplateUtil instance = new RestTemplateUtil();

    @Autowired
    private RestTemplate restTemplate;

    private RestTemplateUtil() {}

    public static RestTemplateUtil getInstance() {
        return instance;
    }

    // 对单例类中对象注入
    @PostConstruct
    public void init() {
        instance = this;  
        instance.restTemplate = this.restTemplate;
    }
}    

 

posted @ 2016-03-21 16:31  集君  阅读(3009)  评论(0编辑  收藏  举报