<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 262,  comments - 221,  trackbacks - 0
    一、單例模式的陷阱

    設(shè)計(jì)模式中的單例模式應(yīng)該是被大家使用最廣泛的模式之一,但網(wǎng)上關(guān)于單例模式的詬病也不少,最集中的就是:在多線程的環(huán)境下,單例模式有可能返回不止一個的對象。那么到底為什么會出現(xiàn)這種情況呢?下面我們來看單例模式的兩種實(shí)現(xiàn)方式

    方式一

    public class Singleton {

      //注意構(gòu)造方法必須是私有的
          private Singleton(){}

      //在自己內(nèi)部定義自己一個實(shí)例,是不是很奇怪?
      //注意這是private 只供內(nèi)部調(diào)用

      private static Singleton instance = new Singleton();

      //這里提供了一個供外部訪問本class的靜態(tài)方法,可以直接訪問  
      
    public static Singleton getInstance() {
        return instance;   
       }
    }


    方式二
    public class Singleton {

      private static Singleton instance = null;

      
    public static synchronized Singleton getInstance() {

          //這個方法比上面有所改進(jìn),不用每次都進(jìn)行生成對象,只是第一次     
          //使用時(shí)生成實(shí)例!
          if (instance==null)
       
         instance=new Singleton();
                return instance;
          }
           }
    }


    方式二就是我們說的:滯后初始化(Lazy Initialization)。為什么會有滯后初始化這種實(shí)現(xiàn)方式出現(xiàn)呢?我們可用看到在第一種實(shí)現(xiàn)方式中無法向單例模式的構(gòu)造方法傳遞參數(shù),而使用滯后初始化的方式,我們可用在調(diào)用getInstance()方法的時(shí)候向方法中傳遞參數(shù)。


    凡事有好處必然有壞處,滯后初始化的一個弊病就是在多線程或分布式的環(huán)境下有可能出現(xiàn)混亂:

    “有時(shí)在某些情況下,使用Singleton并不能達(dá)到Singleton的目的,如有多個Singleton對象同時(shí)被不同的類裝入器裝載;在EJB這樣的分布式系統(tǒng)中使用也要注意這種情況,因?yàn)镋JB是跨服務(wù)器,跨JVM的。” --摘自www.jdon.com-《GoF 23種設(shè)計(jì)模式解析》

    “在多線程環(huán)境下,我們無法保證一個方法能夠持續(xù)運(yùn)行到結(jié)束,其他線程的方法才開始運(yùn)行。因而可能存在這樣一種情形:兩個線程幾乎同時(shí)嘗試初始化單例類。假設(shè)第一個方法發(fā)現(xiàn)單例為空,而第二個方法在此刻開始運(yùn)行,它也會發(fā)現(xiàn)該單例為空。接下來,這兩個方法都將對該單例進(jìn)行初始化。”  --摘自《Java設(shè)計(jì)模式》


    二、單例模式在多線程下的安全實(shí)現(xiàn)

    《Java并發(fā)編程》一書建議使用屬于當(dāng)前類的鎖進(jìn)行同步,代碼如下:

    public class Singleton {

        private static Singleton instance = null;
      // 注意這里的static非常重要,如果為對象變量則因?yàn)榇嬖诙喾菘截惗鸩坏较拗频淖饔?/font>
        private static Object classLock = Singleton.class;

         public static Singleton getInstance() {

          //這個方法比上面有所改進(jìn),不用每次都進(jìn)行生成對象,只是第一次     
          //使用時(shí)生成實(shí)例!
              synchronized(classLock){
                  if (instance==null)
              instance=new Singleton();
                  return instance;
              } 
              }      
         }
    }

    在第一個線程開始滯后初始化的時(shí)候,如果有另一線程也準(zhǔn)備開始初始化,這時(shí)候,第二個線程將停止執(zhí)行,等待獲取對象classLock的鎖。當(dāng)?shù)诙€線程獲取這個鎖并開始執(zhí)行初始化的時(shí)候,它會發(fā)現(xiàn)該單例已不再為空(因?yàn)橹淮嬖谠擃惖奈ㄓ袑?shí)例,我們可以使用單個靜態(tài)鎖)

    三、使用單例模式的另外一些注意點(diǎn)

    ·單例模式類不能實(shí)現(xiàn)Clonable接口,以防被克隆而產(chǎn)生多個實(shí)例

    ·單例模式類不能實(shí)現(xiàn)Serializable接口,以防被序列化而產(chǎn)生多個實(shí)例



    -------------------------------------------------------------
    生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
    posted on 2008-01-03 22:31 Paul Lin 閱讀(1231) 評論(0)  編輯  收藏 所屬分類: 模式與重構(gòu)
    <2008年1月>
    303112345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

    常用鏈接

    留言簿(21)

    隨筆分類

    隨筆檔案

    BlogJava熱點(diǎn)博客

    好友博客

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲综合成人婷婷五月网址| 亚洲欧洲国产精品久久| 亚洲AV日韩综合一区| 皇色在线视频免费网站| 黄色片免费在线观看| 亚洲情综合五月天| 少妇性饥渴无码A区免费| 国产A在亚洲线播放| 毛片无码免费无码播放 | 四虎影库久免费视频| 一本色道久久综合亚洲精品高清| 国产精品久久亚洲一区二区 | 亚洲高清偷拍一区二区三区| 久久综合亚洲色hezyo| 男人的天堂亚洲一区二区三区 | 国产va在线观看免费| 亚洲国产成人久久综合碰碰动漫3d | 国产免费一区二区三区在线观看| 在线播放亚洲第一字幕| 日本高清免费观看| 中文字幕亚洲综合久久| 黄色免费网站在线看| 日日噜噜噜噜夜夜爽亚洲精品| 中国人免费观看高清在线观看二区 | 国产色婷婷精品免费视频| 高潮毛片无遮挡高清免费视频| 中文字幕亚洲乱码熟女一区二区| 成人无码a级毛片免费| 亚洲精品国产福利片| 国产在线观a免费观看| 久久久婷婷五月亚洲97号色| 手机在线免费视频| 亚洲日韩在线视频| 国产精品嫩草影院免费| 久久99精品免费一区二区| 午夜国产羞羞视频免费网站| 中文字幕乱码免费看电影| 亚洲国产精品xo在线观看| 亚洲AV无码成H人在线观看| 日本免费大黄在线观看| 亚洲爆乳精品无码一区二区|