真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

單例模式之怎么實(shí)現(xiàn)我的機(jī)器人女友

本篇內(nèi)容介紹了“單例模式之怎么實(shí)現(xiàn)我的機(jī)器人女友”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

成都創(chuàng)新互聯(lián)公司專注于浦城企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站建設(shè),成都做商城網(wǎng)站。浦城網(wǎng)站建設(shè)公司,為浦城等地區(qū)提供建站服務(wù)。全流程按需求定制制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

程序代碼如下:


   
   
  
public class GirlFriend {

   private String name;

   public GirlFriend(String name) {
       this.name = name;
       System.out.println("機(jī)器人女友制作完成");
   }

   public void smile() {
       System.out.println("笑一個(gè) :-)");
   }

   public void housework() {
       System.out.println("去干家務(wù)");
   }

   public void buKeMiaoShu() {
       System.out.println(".......");
   }
}
     
操作也很簡單,直接創(chuàng)建對(duì)象就行了。

   
   
  
public static void main(String[] args) {
    GirlFriend girlFriend = new GirlFriend("小麗");
    girlFriend.smile();
    girlFriend.housework();
    girlFriend.buKeMiaoShu();
}
     
你看,馬上就能干活了。

   
   
  
機(jī)器人女友制作完成
笑一個(gè) :-)
去干家務(wù)
.......
     
小帥很快發(fā)現(xiàn)了一個(gè)漏洞,如果材料足夠,他能創(chuàng)造無數(shù)個(gè)對(duì)象。
很快,小帥就在黑市上購買了一套材料,回家啟動(dòng)機(jī)器,果然制造出了第二個(gè)機(jī)器人女友。
小帥難掩心中的興奮,盤算著,再去黑市買幾套材料回來,不就能打印很多個(gè)“女友”了?

單例模式


創(chuàng)新基因公司的監(jiān)控系統(tǒng)很快就發(fā)現(xiàn)了這個(gè)問題,工程師們加班加點(diǎn)在線升級(jí)了系統(tǒng)。
他們采用了一種叫做單例模式的設(shè)計(jì)模式來保證一臺(tái)機(jī)器只能生成一個(gè)對(duì)象。

單例模式之怎么實(shí)現(xiàn)我的機(jī)器人女友


 更新后的代碼如下:

   
   
  
public class GirlFriend {

   private static GirlFriend girlFriend;

   private String name;

   private GirlFriend(String name) {
       this.name = name;
       System.out.println("機(jī)器人女友制作完成");
   }

   /**
    * 對(duì)象通過getInstance方法獲取
    * @param name
    * @return
    */
   public static GirlFriend getInstance(String name) {
       if(girlFriend == null) {
           girlFriend = new GirlFriend(name);
       }
       return girlFriend;
   }

   public void smile() {
       System.out.println("笑一個(gè) :-)");
   }

   public void housework() {
       System.out.println("去干家務(wù)");
   }

   public void buKeMiaoShu() {
       System.out.println(".......");
   }
}
     

   
   
  
public static void main(String[] args) {
   GirlFriend girlFriend = GirlFriend.getInstance("小麗");
   girlFriend.smile();
   girlFriend.housework();
   girlFriend.buKeMiaoShu();
}
     
創(chuàng)新基因公司的工程師們很滿意,他們開了一個(gè)盛大的party,慶祝工作的圓滿完成。
小帥花了重金,在黑市上買了好幾套材料,打算回家打造一個(gè)“后宮團(tuán)”,想想以后的日子真是美滋滋啊。
小帥打開程序一看傻了眼,運(yùn)行了好多次,獲取的都是同一個(gè)對(duì)象,“后宮”夢(mèng)就此破裂了嗎?
小帥不甘心啊。
經(jīng)過幾天苦思冥想,小帥終于想到了破解方法,這就是多線程:

   
   
  
public static void main(String[] args){
   for(int i = 0; i < 5; i++) {
       new Thread(new Runnable() {
           @Override
           public void run() {
               GirlFriend girlFriend = GirlFriend.getInstance("小麗");
               System.out.println(girlFriend);
           }
       }).start();
   }
}
     
5個(gè)線程同時(shí)運(yùn)行,順利創(chuàng)建了3個(gè)不同的對(duì)象。

   
   
  
機(jī)器人女友制作完成
singleton.singleton.GirlFriend@95458f7
機(jī)器人女友制作完成
機(jī)器人女友制作完成
singleton.singleton.GirlFriend@d9d8ad0
singleton.singleton.GirlFriend@383a0ba
singleton.singleton.GirlFriend@d9d8ad0
singleton.singleton.GirlFriend@d9d8ad0
     
“嗚。嗚。嗚?!?,創(chuàng)新基因公司的報(bào)警器又響了起來,工程師們都一臉懵逼,這么完美的單例模式怎么還有破綻呢?
最后還是技術(shù)總監(jiān)親自出馬,給工程師們講解,順便畫了一幅圖:

單例模式之怎么實(shí)現(xiàn)我的機(jī)器人女友


 線程1和線程2判斷girlFriend的時(shí)候如果都為空,就會(huì)各自創(chuàng)建一個(gè)對(duì)象,最后就會(huì)返回兩個(gè)不同的對(duì)象了。

工程師們恍然大悟。
“誰知道如何改進(jìn)嗎?”技術(shù)總監(jiān)問道。

懶漢式

“這個(gè)簡單,在getInstance方法上加個(gè)synchronized關(guān)鍵字就行了!”程序員老王得意的說。

   
   
  
/**
* 對(duì)象通過getInstance方法獲取
 * @param name
 * @return
 */
public synchronized static GirlFriend getInstance(String name) {
    if(girlFriend == null) {
        girlFriend = new GirlFriend(name);
    }
    return girlFriend;
}
     
“這樣確實(shí)可以,不過,”技術(shù)總監(jiān)話鋒一轉(zhuǎn),“你有沒有考慮過效率問題?”
“synchronized同步方法只有第一次創(chuàng)建對(duì)象的時(shí)候能用到,也就是說一旦創(chuàng)建了girlFriend對(duì)象后就用不到這個(gè)同步功能了,但是以后每次調(diào)用getInstance方法都會(huì)進(jìn)入同步代碼,嚴(yán)重降低了效率。”
技術(shù)總監(jiān)犀利地指出了問題所在。

餓漢式

“還有個(gè)辦法,可以用全局變量,在類加載的時(shí)候就創(chuàng)建對(duì)象,所以,實(shí)例的創(chuàng)建過程是線程安全的?!背绦騿T小李也想出了一個(gè)辦法。

   
   
  
public class GirlFriend {

   // 在類加載的時(shí)候就創(chuàng)建對(duì)象,是線程安全的
   private static GirlFriend girlFriend = new GirlFriend("小麗");

   private String name;

   private GirlFriend(String name) {
       this.name = name;
       System.out.println("機(jī)器人女友制作完成");
   }

   /**
    * 對(duì)象通過getInstance方法獲取
    * @return
    */
   public static GirlFriend getInstance() {
       return girlFriend;
   }

   public void smile() {
       System.out.println("笑一個(gè) :-)");
   }

   public void housework() {
       System.out.println("去干家務(wù)");
   }

   public void buKeMiaoShu() {
       System.out.println(".......");
   }
}
     
技術(shù)總監(jiān)說:“這是個(gè)辦法,不過,這樣的實(shí)現(xiàn)方式有幾個(gè)問題需要考慮?!?/section>
  • 不支持延遲加載(在真正用到對(duì)象的時(shí)候,再創(chuàng)建實(shí)例),在類加載的時(shí)候?qū)ο缶蛣?chuàng)建好了,如果對(duì)象在整個(gè)程序中一次都用不到,提前創(chuàng)建就浪費(fèi)了。

  • 不能控制對(duì)象的數(shù)量,我們完全可以聲明多個(gè)對(duì)象,比如:GirlFriend girlFriend1;GirlFriend girlFriend2;GirlFriend girlFriend3。

  • 我們可能沒有足夠的信息在靜態(tài)初始化時(shí),實(shí)例化每一個(gè)對(duì)象,對(duì)象的構(gòu)造方法參數(shù),可能要依賴程序后面的運(yùn)算結(jié)果。


但是,我們要活學(xué)活用,如果創(chuàng)建對(duì)象比較耗時(shí),等我們用到的時(shí)候再創(chuàng)建就會(huì)很慢,我們想在程序加載的時(shí)候提前創(chuàng)建好,是可以用這種方式的。  
“還有沒有其他方法?”技術(shù)總監(jiān)追問道。

雙重檢測(cè)

“還有一種辦法,把同步鎖放到方法里面,雙重檢測(cè)?!背绦騿T老王想了好久,終于想出了另一種方法。

   
   
  
public class GirlFriend {

   // volatile關(guān)鍵字保證了每個(gè)線程看到的girlFriend對(duì)象都是最新的
   private volatile static GirlFriend girlFriend;

   private String name;

   private GirlFriend(String name) {
       this.name = name;
       System.out.println("機(jī)器人女友制作完成");
   }

   /**
    * 對(duì)象通過getInstance方法獲取
    * @param name
    * @return
    */
   public static GirlFriend getInstance(String name) {
       if(girlFriend == null) {
           synchronized (GirlFriend.class) {
               if (girlFriend == null) {
                   girlFriend = new GirlFriend(name);
               }
           }
       }
       return girlFriend;
   }

   public void smile() {
       System.out.println("笑一個(gè) :-)");
   }

   public void housework() {
       System.out.println("去干家務(wù)");
   }

   public void buKeMiaoShu() {
       System.out.println(".......");
   }
}
     
“檢查girlFriend對(duì)象的時(shí)候,如果為null就進(jìn)入同步代碼,每個(gè)線程重新判斷girlFriend對(duì)象是否為空,volatile關(guān)鍵字保證了每個(gè)線程看到的girlFriend對(duì)象都是最新的(在高版本的 Java中,這里已經(jīng)不需要使用volatile了)?!?/section>
“如果girlFriend對(duì)象已經(jīng)創(chuàng)建了,以后就不會(huì)進(jìn)入同步代碼了,這樣就保證了效率。”老王解釋道。
“恩,這是個(gè)好方法,這樣就解決懶漢式方法的低性能和餓漢式方法的延遲加載問題,我們就采用這個(gè)方案升級(jí)代碼吧?!奔夹g(shù)總監(jiān)贊許道。

總結(jié)

單例模式(Singleton Pattern):單例模式確保一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。
單例模式的有三個(gè)要點(diǎn):
  • 某個(gè)類只能有一個(gè)實(shí)例

  • 它必須自行創(chuàng)建這個(gè)實(shí)例

  • 它必須自行向整個(gè)系統(tǒng)提供這個(gè)實(shí)例

單例模式是一種對(duì)象創(chuàng)建型模式。
單例模式又名單件模式或單態(tài)模式。
單例的實(shí)現(xiàn)單例有下面幾種經(jīng)典的實(shí)現(xiàn)方式:
- 懶漢式
懶漢式相對(duì)于餓漢式的優(yōu)勢(shì)是支持延遲加載。但是,這種實(shí)現(xiàn)方式會(huì)導(dǎo)致頻繁加鎖、釋放鎖,以及并發(fā)度低等問題,頻繁的調(diào)用會(huì)產(chǎn)生性能瓶頸。
- 餓漢式
餓漢式的實(shí)現(xiàn)方式,在類加載的期間,就已經(jīng)將靜態(tài)實(shí)例初始化好了,所以,實(shí)例的創(chuàng)建是線程安全的。不過,這樣的實(shí)現(xiàn)方式不支持延遲加載實(shí)例。
- 雙重檢測(cè)
雙重檢測(cè)的實(shí)現(xiàn)方式是既支持延遲加載、又支持高并發(fā)的單例實(shí)現(xiàn)方式。只要實(shí)例被創(chuàng)建之后,再調(diào)用 getInstance() 函數(shù)都不會(huì)進(jìn)入到加鎖邏輯中。

“單例模式之怎么實(shí)現(xiàn)我的機(jī)器人女友”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!


當(dāng)前題目:單例模式之怎么實(shí)現(xiàn)我的機(jī)器人女友
轉(zhuǎn)載源于:http://weahome.cn/article/ijhoge.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部