亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java 單例模式容易忽略的細節(jié)

 更新時間:2020年12月24日 11:38:53   作者:努力的老劉  
這篇文章主要介紹了java 單例模式容易忽略的細節(jié),幫助大家更好的理解和使用java 單例模式,感興趣的朋友可以了解下

java單例模式

直接講實現單例模式的兩種方法:懶漢式和餓漢式,單例模式的概念自己上網搜吧這里就不講了!

這里會涉及到java中的jvm,如果你沒有這方面的知識,我建議你先去補補,不然會有點迷糊!

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

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

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

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

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

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

先看最開始的代碼:

public class Student2 {

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

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

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

線程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先進去執(zhí)行完后,線程2才能進去,然后第二個if判斷是否完成創(chuàng)建類的實例,線程1創(chuàng)建完了,線程2就不用創(chuàng)建了。

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

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

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

2、分配內存空間

3、將對象進行初始化4、講對象引用地址賦值給??臻g中的變量但我們JVM中的JIT即時編輯器會對代碼的執(zhí)行過程進行優(yōu)化,把過程變?yōu)?、2、4、3。

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

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

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

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

看代碼:

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先執(zhí)行getSingletonInstance()時,就會進行類加載,類的靜態(tài)資源就會進行初始化。根據JVM安全機制里說的,當一個類被JVM加載的時候,該類的加載是線程安全的,相當于JVM對該過程加鎖了。所以整個過程處于一個鎖的范圍內,然后靜態(tài)成員變量進行初始化就相當于Student1()被new了,只會被new一次。

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

總結

老劉看過很多關于java單例模式的資料,多多少少都會缺少一點細節(jié),這次老劉把它補全了。

最后,如果覺得有哪里寫的不好或者有錯誤的地方,可以聯(lián)系公眾號:努力的老劉,進行交流。

如果覺得寫的不錯,給老劉點個贊!

以上就是java 單例模式容易忽略的細節(jié)的詳細內容,更多關于java 單例模式的資料請關注腳本之家其它相關文章!

相關文章

  • 踩坑批量更新sql報錯,實際sql能夠正常執(zhí)行的問題

    踩坑批量更新sql報錯,實際sql能夠正常執(zhí)行的問題

    在項目工程遷移過程中,遇到了一個批量更新接口在新工程中報錯的問題,通過分析,排除了代碼錯誤的可能,最終發(fā)現是由于數據庫連接配置不當導致的,在jdbc連接字符串中加入allowMultiQueries=true參數后,問題得以解決,這個參數的作用是允許SQL批量執(zhí)行
    2022-12-12
  • Java C++題解leetcode 1684統(tǒng)計一致字符串的數目示例

    Java C++題解leetcode 1684統(tǒng)計一致字符串的數目示例

    這篇文章主要為大家介紹了Java C++題解leetcode 1684統(tǒng)計一致字符串的數目示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • MyBatis數據脫敏的實現方案介紹

    MyBatis數據脫敏的實現方案介紹

    在我們數據庫中有些時候會保存一些用戶的敏感信息,比如:手機號、銀行卡等信息,如果這些信息以明文的方式保存,那么是不安全的
    2022-08-08
  • Eureka源碼核心類預備知識

    Eureka源碼核心類預備知識

    這篇文章主要為大家介紹了Eureka源碼核心類預備知識詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • IDEA遠程管理docker鏡像及容器服務的實現

    IDEA遠程管理docker鏡像及容器服務的實現

    本文主要介紹了IDEA遠程管理docker鏡像及容器服務的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • 全面了解Java中Native關鍵字的作用

    全面了解Java中Native關鍵字的作用

    下面小編就為大家?guī)硪黄媪私釰ava中Native關鍵字的作用。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • SpringBoot動態(tài)定時任務實現完整版

    SpringBoot動態(tài)定時任務實現完整版

    最近有幸要開發(fā)個動態(tài)定時任務,這里簡單再梳理一下,下面這篇文章主要給大家介紹了關于SpringBoot動態(tài)定時任務實現的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-02-02
  • 詳解eclipse創(chuàng)建maven項目實現動態(tài)web工程完整示例

    詳解eclipse創(chuàng)建maven項目實現動態(tài)web工程完整示例

    這篇文章主要介紹了詳解eclipse創(chuàng)建maven項目實現動態(tài)web工程完整示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • 教你怎么用Java開發(fā)掃雷游戲

    教你怎么用Java開發(fā)掃雷游戲

    我們那時候上機經常玩掃雷,試想如果我當年可以用 java 寫個掃雷出來,那場面不用我多說了吧,大家讓開,我要開始裝逼了,之前用JavaScript寫過了一個掃雷,這次我用java再寫了一遍,權當是復習咯.文中有非常詳細的代碼示例,需要的朋友可以參考下
    2021-05-05
  • Java實現選擇排序算法的實例教程

    Java實現選擇排序算法的實例教程

    這篇文章主要介紹了Java實現選擇排序算法的實例教程,選擇排序的時間復雜度為О(n²),需要的朋友可以參考下
    2016-05-05

最新評論