歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java設計模式之單例模式及其應用

一、 單例模式概述

Java中單例模式的定義是:一個類只有一個實例,而且自行實例化並且向整個系統提供這個實例。

優點:由於單例模式在內存中只有一個實例,減少了內存開支和系統的性能開銷;單例模式可以避免對資源的多重占用。

二、單例模式的幾種形式

1.  餓漢式單例

public class Singleton {
 private static final Singleton singleton= new Singleton();
 private Singleton(){
 }
 public Singleton getSingleton(){
  return singleton;
 }
}

餓漢式是線程安全的,在類開始加載的時候就完成了單例的初始化。線程安全在java並發編程實戰中是這樣定義的:當多個線程訪問某個類時,不管運行時環境采用何種調度方式或者這些線程將如何交替執行,並且在主調代碼中不需要任何額外的同步或者協同,這個類都能表現出正確的行為,那麼就稱這個類是線程安全的。

2.懶漢式單例

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

懶漢式不是線程安全的,並發環境下,可能出現多個single對象。要實現線程安全,可以采用雙重鎖:

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

三、單例模式在spring中的應用

DefaultSingletonBeanRegistry類中的getSingleton方法:

/** Cache of singleton objects: bean name --> bean instance */
 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

 /** Cache of singleton factories: bean name --> ObjectFactory */
 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

 /** Cache of early singleton objects: bean name --> bean instance */
 private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

 
 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 // map緩存中查看是否存在實例
  Object singletonObject = this.singletonObjects.get(beanName);
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
   synchronized (this.singletonObjects) {
    singletonObject = this.earlySingletonObjects.get(beanName);
    if (singletonObject == null && allowEarlyReference) {
     ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
     if (singletonFactory != null) {
      singletonObject = singletonFactory.getObject();
      this.earlySingletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
     }
    }
   }
  }
  return (singletonObject != NULL_OBJECT ? singletonObject : null);
 }

從上面的代碼中可以看出spring在獲取單例bean的時候,采用了雙重判斷加鎖的單例模式,首先嘗試從map緩存singletonObjects中獲取實例,如果獲取不到,對singletonObjects加鎖,再到map緩存earlySingletonObjects裡面獲取,如果還是為null,就創建一個bean,並放到earlySingletonObjects中去。

Copyright © Linux教程網 All Rights Reserved