中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

在java中使用單例模式時需要注意哪些事項

發布時間:2020-12-24 16:01:26 來源:億速云 閱讀:145 作者:Leah 欄目:開發技術

這篇文章將為大家詳細講解有關在java中使用單例模式時需要注意哪些事項,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

java單例模式

單例模式的兩種方法:懶漢式和餓漢式

首先說說類什么時候進行加載?

java虛擬機沒有進行強制性的約束,但是對于初始化卻嚴格規定了有且只有4種情況必須先對類進行初始化。

我們要知道的是在類加載的過程中,加載、驗證、準備是在初始化之前完成的,所以進行了初始化,加載、驗證、準備自然就在之前完成了。

然后這四種情況是分別遇到 new 、 getstatic 、 putstatic 和 invokestatic 這四條指令時,如果對應的類沒有初始化,則要對對應的類先進行初始化。

講完類加載時機,就可以講懶漢式和餓漢式了。

直接先說說懶漢式為什么是線程不安全的?

先看最開始的代碼:

public class Student2 {

  //1:構造私有
  private Student2(){}
  //2:定義私有靜態成員變量,先不初始化
  private static Student2 student = null;

  //3:定義公開靜態方法,獲取本身對象
  public static Student2 getSingletonInstance(){
    //沒有對象,再去創建
    if (student == null) {
      student = new Student2();
    }
    //有對象就返回已有對象
    return student;
  }  
}

結合之前講的類加載內容,遇到new或加載靜態方法了就會進行類加載了。

線程1它new了一個對象,線程2它緊接著也new一個對象,第二個對象的值把第一個對象的值覆蓋了,不管new了多少個對象,都會產生垃圾對象,只有最后一個對象才會保持住,其他對象都會變成不可達對象,被垃圾回收,這個過程就相當于產生了大量無效對象,這就是線程不安全的原因!

那為了讓懶漢式變得線程安全,我們要怎么做?

看代碼:

public class Student4 {

  private volatile static Student4 student = null;
  private Student4() {}

  public static Student4 getSingletonInstance() {
    if (student == null) {//第一個null判斷,是先大范圍過濾一遍
      synchronized (Student4.class) {
        if (student == null) {
          student = new Student4();
        }
      }
    }
    return student;
  }
}

這個叫雙重檢查鎖DCL,第一個if先大范圍判斷是不是空值,經過synchronized,線程1先進去執行完后,線程2才能進去,然后第二個if判斷是否完成創建類的實例,線程1創建完了,線程2就不用創建了。

那為什么要加volatile關鍵字呢?

因為我們Student student = new Student()的執行過程是:

1、new觸發類加載機制(已經被加載過的類不需要再次加載)

2、分配內存空間

3、將對象進行初始化4、講對象引用地址賦值給棧空間中的變量但我們JVM中的JIT即時編輯器會對代碼的執行過程進行優化,把過程變為1、2、4、3。

這是什么意思呢?就是未經初始化直接賦值,這樣就是student直接有值了,但整個對象還未初始化完成,所以這個對象是不完整的,是個未成品。在JVM規范中,它是一個根本不能用的對象。

到了這個時候,線程1做了這么多事,我們讓它休息會,給CPU稍微停一下,線程2就來了,它就直接得到了對象,但它調用對象的方法時,就會報錯。雖然這個對象有值,但還未初始化完成。所以我們要加上volatile關鍵字禁止指令重新排序。

面試重災區說的差不多了,餓漢式還是要講講。

最后就說說餓漢式為什么沒有線程安全問題?

看代碼:

public class Student1 {
  // 2:成員變量初始化本身對象
  private static Student1 student = new Student1();
  // 構造私有
  private Student1() {
  }
  // 3:對外提供公共方法獲取對象
  public static Student1 getSingletonInstance() {
    return student;
  }
  public void sayHello(String name) {
    System.out.println("hello," + name);
  }
}

根據類加載的東西,在多線程的條件下,線程1先執行getSingletonInstance()時,就會進行類加載,類的靜態資源就會進行初始化。根據JVM安全機制里說的,當一個類被JVM加載的時候,該類的加載是線程安全的,相當于JVM對該過程加鎖了。所以整個過程處于一個鎖的范圍內,然后靜態成員變量進行初始化就相當于Student1()被new了,只會被new一次。

當第二個線程進來,它就發現這個類已經被加載了,就不需要進行加載了,對象也不需要頻繁創建,所以線程是安全的!

關于在java中使用單例模式時需要注意哪些事項就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

莱州市| 渑池县| 峨眉山市| 双鸭山市| 桦川县| 吉木萨尔县| 哈密市| 广宁县| 乌兰浩特市| 武川县| 遂溪县| 贺兰县| 临安市| 汝南县| 同仁县| 新平| 曲阳县| 三台县| 山丹县| 乌拉特中旗| 青铜峡市| 吉木乃县| 固阳县| 克什克腾旗| 呼玛县| 宁国市| 海宁市| 如皋市| 娱乐| 昌吉市| 华蓥市| 招远市| 泰和县| 遵化市| 平塘县| 乳山市| 金山区| 嵩明县| 许昌市| 微博| 东至县|