中文JAVA技術(shù)平等自由協(xié)作創(chuàng)造

          Java專題文章博客和開源

          常用鏈接

          統(tǒng)計(jì)

          最新評(píng)論

          JAVA中單例模式的幾種實(shí)現(xiàn)方式

            1 線程不安全的實(shí)現(xiàn)方法

            首先介紹java中最基本的單例模式實(shí)現(xiàn)方式,我們可以在一些初級(jí)的java書中看到。這種實(shí)現(xiàn)方法不是線程安全的,所以在項(xiàng)目實(shí)踐中如果涉及到線程安全就不會(huì)使用這種方式。但是如果不需要保證線程安全,則這種方式還是不錯(cuò)的,因?yàn)樗枰拈_銷比較小。下面是具體的實(shí)現(xiàn)代碼:

            public Class Singleton

            {

            private static Singleton instance = null;

            private Singleton(){}

            public static Singleton getInstance()

            {

            if( instance == null)

            instance = new Singleton ();

            return instance;

            }

            }

            我們說過這種實(shí)現(xiàn)方式不是thread-safe的,那么可以把上面的方法變成線程安全的嗎?當(dāng)然可以,在方法getInstance()上加上synchronized修飾符就可以實(shí)現(xiàn)方法的同步了。但是這樣系統(tǒng)開銷會(huì)很大。具體代碼如下:

            public Class Singleton

            {

            private static Singleton instance = null;

            private Singleton(){}

            public static synchronized Singleton getInstance()

            {

            if( instance == null)

            instance = new Singleton ();

            return instance;

            }

            }

            每次有線程調(diào)用getInstance()方法,都需要同步判斷。這顯然不是最好的選擇,下面將會(huì)陸續(xù)介紹幾種thread-safe的方法。

            2 兩種lazy loaded thread-safe的單例模式實(shí)現(xiàn)方式

            1) DCL (double checked locking 實(shí)現(xiàn)法)

            double checked locking ,顧名思義,就是雙檢查法,檢查實(shí)例INSTANCE是否為null或者已經(jīng)實(shí)例化了。下面是具體的實(shí)現(xiàn)代碼:

            1 public class DoubleCheckedLockingSingleton{

            2 private volatile DoubleCheckedLockingSingleton INSTANCE;

            3

            4 private DoubleCheckedLockingSingleton(){}

            5

            6 public DoubleCheckedLockingSingleton getInstance(){

            7 if(INSTANCE == null){

            8 synchronized(DoubleCheckedLockingSingleton.class){

            9 //double checking Singleton instance

            10 if(INSTANCE == null){

            11 INSTANCE = new DoubleCheckedLockingSingleton();

            12 }

            13 }

            14 }

            15 return INSTANCE;

            16 }

            17 }

            這種方法也很好理解,我們可以看到有兩次對(duì)instance是否為null的判斷:如果第一次判斷不為空,則直接返回實(shí)例就可以了;如果instance為空,則進(jìn)入同步代碼塊再進(jìn)行null值判斷,再選擇是否實(shí)例化。第一個(gè)null判斷可以減少系統(tǒng)的開銷。在實(shí)際項(xiàng)目中做過多線程開發(fā)的都應(yīng)該知道DCL.

            2) lazy initialization holder class 模式實(shí)現(xiàn)法

            下面是這種方法的實(shí)現(xiàn)代碼:

            public class Singleton {

            /**

            * 類級(jí)的內(nèi)部類,也就是靜態(tài)的成員式內(nèi)部類,該內(nèi)部類的實(shí)例與外部類的實(shí)例

            * 沒有綁定關(guān)系,而且只有被調(diào)用到才會(huì)裝載,從而實(shí)現(xiàn)了延遲加載

            */

            private static class SingletonHolder{

            /**

            * 靜態(tài)初始化器,由JVM來保證線程安全

            */

            private static Singleton instance = new Singleton();

            }

            /**

            * 私有化構(gòu)造方法

            */

            private Singleton(){

            }

            public static Singleton getInstance(){

            return SingletonHolder.instance;

            }

            }

            當(dāng)getInstance方法第一次被調(diào)用的時(shí)候,它第一次讀取SingletonHolder.instance,導(dǎo)致SingletonHolder類得到初始化;而這個(gè)類在裝載并被初始化的時(shí)候,會(huì)初始化它的靜態(tài)域,從而創(chuàng)建Singleton的實(shí)例,由于是靜態(tài)的域,因此只會(huì)被虛擬機(jī)在裝載類的時(shí)候初始化一次,并由虛擬機(jī)來保證它的線程安全性。這個(gè)模式的優(yōu)勢(shì)在于,getInstance方法并沒有被同步,并且只是執(zhí)行一個(gè)域的訪問,因此延遲初始化并沒有增加任何訪問成本。

            關(guān)于延遲初始化(lazy loaded)

            "除非絕對(duì)必要,否則就不要延遲初始化".延遲初始化是一把雙刃劍,它降低了初始化類或者創(chuàng)建實(shí)例的開銷,卻增加了訪問被延遲初始化的域的開銷,考慮到延遲初始化的域最終需要初始化的開銷以及域的訪問開銷,延遲初始化實(shí)際上降低了性能雅思答案 tygj123.com

            3 靜態(tài)工廠實(shí)現(xiàn)法

            因?yàn)閱卫庆o態(tài)的final變量,當(dāng)類第一次加載到內(nèi)存中的時(shí)候就初始化了,其thread-safe性由JVM來負(fù)責(zé)保證。值得注意的是這個(gè)實(shí)現(xiàn)方式不是lazy-loadedd的。 具體實(shí)現(xiàn)代碼如下:

            1 public class Singleton{

            2 //initailzed during class loading

            3 private static final Singleton INSTANCE = new Singleton();

            4

            5 private Singleton(){}

            6

            7 public static Singleton getSingleton(){

            8 return INSTANCE;

            9 }

            10 }

            4 枚舉實(shí)現(xiàn)單例(Enum Singleton)

            枚舉單例(Enum Singleton)是實(shí)現(xiàn)單例模式的一種新方式,枚舉這個(gè)特性是在Java5才出現(xiàn)的,在《Effective Java》一書中有介紹這個(gè)特性。下面是這種方法的具體實(shí)現(xiàn)代碼:

            public enum Singleton {

            INSTANCE("hello") {

            public void someMethod() {

            // . . .

            }

            };

            private String name;

            private void PrintName(){System.out.println(name);}

            protected abstract void someMethod();

            }

            你可以通過Singleton.INSTANCE來訪問該單示例變量。默認(rèn)枚舉實(shí)例的創(chuàng)建是線程安全的,但是在枚舉中的其他任何方法由程序員自己負(fù)責(zé)。如果你正在使用實(shí)例方法,那么你需要確保線程安全(如果它影響到其他對(duì)象的狀態(tài)的話)。傳統(tǒng)單例存在的另外一個(gè)問題是一旦你實(shí)現(xiàn)了序列化接口,那么它們不再保持單例了,但是枚舉單例,JVM對(duì)序列化有保證。枚舉實(shí)現(xiàn)單例的好處:有序列化和線程安全的保證,代碼簡(jiǎn)單。 www.yz-lc.com
           

          posted on 2014-03-06 14:20 好不容易 閱讀(170) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          PK10開獎(jiǎng) PK10開獎(jiǎng)
          主站蜘蛛池模板: 清水县| 宁化县| 永兴县| 哈尔滨市| 龙井市| 海伦市| 陆河县| 阿合奇县| 新兴县| 屏山县| 农安县| 扎兰屯市| 双辽市| 磴口县| 通化县| 舒兰市| 桐乡市| 灌南县| 郑州市| 邛崃市| 铜梁县| 广安市| 定南县| 北宁市| 天祝| 剑川县| 南陵县| 东丽区| 江永县| 墨江| 衡东县| 大连市| 确山县| 台中县| 当阳市| 黔西县| 民丰县| 敖汉旗| 玉山县| 惠安县| 通州市|