平時使用單例的情況很多,至於爲什麼使用在此文章中就不在重複,百度、谷歌一大堆。而單例模式分爲立即加載和延遲加載兩種,這兩種在多線程下都存在安全問題,因此很多時候我們會使用sychronized關鍵字或者代碼塊來保證我們的單例是線程安全的。
本文向各位推薦一種美觀而簡潔,並且線程安全的寫法。
目標:
延遲加載
由於方法同步會降低效率,因此要提高效率(通常做法會使用雙檢查[Double-Check],即先判斷單例對象是否爲空,如果爲空則才進入sychronized代碼塊來對單例對象進行實例化),提高同步的效率
不使用sychronized代碼塊或者關鍵字
原理:
延遲加載這個就是我們調用getInstance方法的時候,纔對單例對象進行初始化或者直接返回,我們使用內部類來作爲延遲加載的解決辦法
我們不需要進行手工的判斷是否需要去實例化該單例,保證我們的內存中確實只有一個實例存在
初始化內部類的時候,JLS(Java Language Sepcification)會保證這個類的線程安全
代碼:
package com.troy.young.thread; /** * 線程安全的單例類 * * @author Administrator * */ public class SingleTon { /** * 定義他的構造方法,讓外部沒有辦法是用new去構造該對象 */ private SingleTon() { } /** * 定義內部類對單例進行實例化。 * 首先內部類是static的,保證了該類在內存中只有一份,同時他的成員變量是final static的,則又再次保證他的單一性。 * 同時由於JLS會保證類的線程安全。 * @author Administrator * */ private static class SingleTonHolder { public final static SingleTon instance = new SingleTon(); } /** * 提供獲取實例的方法 * @return */ public static SingleTon getInstance() { // 直接獲取內部類的變量 return SingleTonHolder.instance; } }
到此我們可以看到,這個代碼既簡潔有安全,可以放在我們的項目中作爲一個嘗試。