java設計模式——單例模式(三)
阿新 • • 發佈:2018-12-11
容器單例模式
之前學習Structs2,Spring框架時,經常會聽到單例,多例。雖然這與單例模式不太一樣,但是都很類似。在程式執行的時候,就載入所有的例項,然後用的時候直接取出
看下面程式碼:
/** * @program: designModel * @description: 容器單例模式 * @author: YuKai Fan * @create: 2018-12-11 14:59 **/ public class ContaineSingleton { private ContaineSingleton() {} private static Map<String, Object> singletonMap = newHashMap<String, Object>(); public static void putInstance(String key, Object instance) { if (StringUtils.isNotBlank(key) && instance != null) { if (!singletonMap.containsKey(key)) { singletonMap.put(key, instance); } } }public static Object getInstance(String key) { return singletonMap.get(key); } }
但是,這種方式在不考慮序列化與反射的情況下,依舊是不安全的。因為在多執行緒的環境下,還是會產生不同的例項,這需要結合場景來使用。
如果使用hashTable來保證執行緒安全的話,效率會很低,頻繁去取例項都回家加同步鎖。如果使用ConcurrentHashMap,由於被static修飾,相當於直接操作了 map,在這種場景下,也不是絕對的執行緒安全。
ThreadLocal環境下的"單例模式"
這種帶引號的單例模式,並不是真正的單例模式。因為並不能保證整個應用只產生一個例項,只會保證整個應用執行緒唯一
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2018-12-11 15:17 **/ public class ThreadLocalInstance { private static final ThreadLocal<ThreadLocalInstance> threadLocalInstance = new ThreadLocal<ThreadLocalInstance>(){ @Override protected ThreadLocalInstance initialValue() { return new ThreadLocalInstance(); } }; private ThreadLocalInstance() {} public static ThreadLocalInstance getInstance() { return threadLocalInstance.get(); } }
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2018-12-04 14:11 **/ public class T implements Runnable { public void run() { ThreadLocalInstance instance = ThreadLocalInstance.getInstance(); System.out.println(Thread.currentThread().getName() + "" + instance); } }
/** * @program: designModel * @description: * @author: YuKai Fan * @create: 2018-12-04 14:07 **/ public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException { // LazySingleton lazySingleton = LazySingleton.getInstance(); Thread t1 = new Thread(new T()); Thread t2 = new Thread(new T()); t1.start(); t2.start(); System.out.println("測試"); } }
輸出結果:
產生的是不同的例項,但是ThreadLocal回味每個執行緒提供獨立的變數副本,將每個執行緒的例項隔離。保證在多執行緒的情況下,會保證每個執行緒只能產生一個例項
單例模式原始碼分析
單例模式在jdk下的應用:
java.lang.Runtime下的getRuntime()方法,屬於餓漢式
AWT下的Desktop類中的getDesktop()