1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      java單例模式怎么定義

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

      創(chuàng)新互聯(lián)公司長期為1000多家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為興安盟企業(yè)提供專業(yè)的做網(wǎng)站、成都做網(wǎng)站,興安盟網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

      一、單例模式定義:
      單例模式確保某個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例。在計算機系統(tǒng)中,線程池、緩存、日志對象、對話框、打印機、顯卡的驅(qū)動程序?qū)ο蟪1辉O(shè)計成單例。這些應(yīng)用都或多或少具有資源管理器的功能。每臺計算機可以有若干個打印機,但只能有一個Printer Spooler,以避免兩個打印作業(yè)同時輸出到打印機中。每臺計算機可以有若干通信端口,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調(diào)用。總之,選擇單例模式就是為了避免不一致狀態(tài),避免政出多頭。

      1、經(jīng)典餓漢式:

      public class Singleton {
          private final static Singleton INSTANCE = new Singleton();
          private Singleton(){}
          public static Singleton getInstance(){
              return INSTANCE;
          }
      }
      特點:程序啟動時加載,先加載類,再初始化靜態(tài)屬性,由于后面無法再對對象進行修改,從而實現(xiàn)線程安全,效率相對高一些。占用內(nèi)存相對多一些。

      缺點:如果這個類特別龐大,初始化時將會特別緩慢,還有就是如果我們用不到這個類,它仍然會創(chuàng)建出來,浪費了資源。

      2、經(jīng)典懶漢式:

      public class Singleton {
          private static Singleton singleton;
          private Singleton() {}
          public static synchronized Singleton getInstance() {
              if (singleton == null) {
                  singleton = new Singleton();
              }
              return singleton;
          }
      }
      特點:延時加載,節(jié)約了內(nèi)存。效率相對低一些。利用同步塊實現(xiàn)線程安全。

      缺點:synchronized關(guān)鍵字是一個重鎖(對象鎖),它會每次調(diào)用getInstance(),都要對對象上鎖,事實上,只有在第一次創(chuàng)建對象的時候需要加鎖,之后就不需要了。

      3、懶漢式變種—雙重檢查結(jié)構(gòu)(不加volatile關(guān)鍵字修飾):

      package cn.hzy.creationPattern.singleton;
       
      public class Singleton3 {
          private static Singleton3 instance = null;
          private Singleton3(){    
          }
          public static Singleton3 getInstance(){
              if (instance == null) {
                  synchronized (instance) {
                  if (instance == null) {
                      instance = new Singleton3();
              }
              }
              }
          return instance;
          }
      }
      特點:屬于懶漢式的變種,上面懶漢式的特點都有,但是這里優(yōu)化了性能問題,沒有給getInstance()方法加鎖,而是只給instance = new Singleton3();加鎖,也就是說只在初始化的時候會加鎖,后面的訪問因為instance!=null,就不會加鎖。

      缺點:乍一看這種模式既沒有線程安全問題,又保證了單例,貌似完美了,但是JVM在創(chuàng)建對象的時候有可能為了優(yōu)化性能而進行指令重排,

      看似簡單的一句     instance = new Singleton3();   JVM在創(chuàng)建對象的時候會有三個步驟:

      1、給Singleton3分配一個內(nèi)存空間

      2、初始化Singleton3(也就是創(chuàng)建Singleton3對象)

      3、將instance指向剛分配的內(nèi)存空間地址

      但是有可能JVM為了編譯的優(yōu)化提高效率就有可能變成下面一種順序:

      1、給Singleton3分配一個內(nèi)存空間

      2、將instance指向剛分配的內(nèi)存空間地址

      3、初始化Singleton3(也就是創(chuàng)建Singleton3對象)

      其實這種情況在單線程情況下是毫無影響的,結(jié)果都一樣,但是如果在多線程情況下,就有可能導(dǎo)致錯誤。

      比如:A、B兩個線程訪問getInstance()方法,A先進入第一個if判斷,然后進入synchronized塊,開始初始化Singleton3,由于發(fā)生了指令重排,將instance指向剛分配的內(nèi)存空間地址(此時未創(chuàng)建Singleton3對象),在這個時候,B訪問getInstance()方法,B進入第一個if判斷,因為instance已經(jīng)指向了一個存在的內(nèi)存空間地址,即instance!=null,此時直接返回instance(未初始化),然后再調(diào)用的時候如果A還沒有初始化完畢那么就會報空指針錯誤。(概率很低)

      解決方案:加上volatile關(guān)鍵字修飾,

      volatile:

      特性一:內(nèi)存可見性,即線程A對volatile變量的修改,其他線程獲取的volatile變量都是最新的。

      特性二:可以禁止指令重排序。

      修改如下:將   private static Singleton3 instance = null;   改為   private static volatile Singleton3 instance = null;

      4、靜態(tài)內(nèi)部類:

      package cn.hzy.creationPattern.singleton;
       
      public class Singleton4 {
          private Singleton4() {}
          
          public static Singleton4 getInstance() {
              return SingletonFactory.instance;
          }
              
          private static class SingletonFactory {
          private static Singleton4 instance = new Singleton4();
          }
      }
      特點:按特征也是屬于懶漢模式,因為只會在我們需要用的時候才會創(chuàng)建實例對象,這里通過構(gòu)造函數(shù)私有化,使用內(nèi)部類來維護單例的實現(xiàn),因為JVM內(nèi)部的機制能夠保證當(dāng)一個類被加載的時候,這個類的加載過程是線程互斥的。這樣當(dāng)我們第一次調(diào)用getInstance的時候,JVM能夠幫我們保證instance只被創(chuàng)建一次, 并且會保證把賦值給instance的內(nèi)存初始化完畢,這樣我們就不用擔(dān)心Singleton3出現(xiàn)的問題。同時該方法也只會在第一次調(diào)用的時候使用互斥機制,這樣就解決了低性能問題。

      缺點:貌似這個就完美了,但是靜態(tài)內(nèi)部類也有著一個致命的缺點,就是傳參的問題,由于是靜態(tài)內(nèi)部類的形式去創(chuàng)建單例的,故外部無法傳遞參數(shù)進去的。

      5、枚舉:

      public enum Singleton {
          INSTANCE;
          public void method() {
          }
      }
      直接調(diào)用SingleTon.INSTANCE就是單例。

      特點:創(chuàng)建枚舉默認就是線程安全的

      優(yōu)點:簡直不要太多,1、寫法簡單,對比上面的實例就能發(fā)現(xiàn)。2、可以防止反射攻擊。

      針對上面的反射攻擊我這里簡單說一下:在上面的1、2、3、4種單例模式里面,如果不對構(gòu)造函數(shù)做一些安全處理,我們可以很輕松通過反射拿到構(gòu)造器并且創(chuàng)建不只一個實例對象,就不再是單例了。但是對于枚舉,即時你通過反射拿到構(gòu)造器,在創(chuàng)建對象實例的時候也會報錯,因為枚舉是可以防止反射攻擊的。

      怎么對構(gòu)造函數(shù)做一些安全處理?

      可以立一個flag,在創(chuàng)建一個對象實例后,改變flag的值,通過判斷拋出異常。

      比如:

      private static boolean flag = false;
      private Singleton (){
          synchronized (Singleton .class) {
              if(false == flag){
                  flag = !flag;
              } else {
                  throw new RuntimeException("單例模式正在被反射攻擊!!!");
              }  
          }
      }
      通過在構(gòu)造函數(shù)里面增加一個判斷來保證不被反射攻擊。

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


      網(wǎng)頁名稱:java單例模式怎么定義
      分享鏈接:http://www.ef60e0e.cn/article/jogcge.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        浮梁县| 万载县| 洪泽县| 年辖:市辖区| 攀枝花市| 兰溪市| 辛集市| 云龙县| 东光县| 福州市| 河源市| 卫辉市| 余干县| 贡山| 元谋县| 承德市| 蓬莱市| 黄平县| 剑河县| 漠河县| 澎湖县| 石棉县| 公主岭市| 金昌市| 沭阳县| 师宗县| 牟定县| 汉沽区| 温泉县| 迁安市| 潞西市| 永泰县| 阜新市| 葫芦岛市| 濮阳市| 清涧县| 富阳市| 巴林左旗| 晋江市| 伊金霍洛旗| 藁城市|