欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

String、StringBuilder、StringBuffer的區(qū)別是什么

本篇內(nèi)容主要講解“String、String Builder、String Buffer的區(qū)別是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“String、String Builder、String Buffer的區(qū)別是什么”吧!

創(chuàng)新互聯(lián)專注于韶關(guān)網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供韶關(guān)營銷型網(wǎng)站建設(shè),韶關(guān)網(wǎng)站制作、韶關(guān)網(wǎng)頁設(shè)計、韶關(guān)網(wǎng)站官網(wǎng)定制、微信小程序開發(fā)服務(wù),打造韶關(guān)網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供韶關(guān)網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

面試官:String,StringBuilder,StringBuffer的區(qū)別是啥?

小宅:這個太簡單了吧,這是看不起我?

  • 從可變性來講String的是不可變的,StringBuilder,StringBuffer的長度是可變的。

  • 從運(yùn)行速度上來講StringBuilder > StringBuffer > String。

  • 從線程安全上來StringBuilder是線程不安全的,而StringBuffer是線程安全的。

??所以 String:適用于少量的字符串操作的情況,StringBuilder:適用于單線程下在字符緩沖區(qū)進(jìn)行大量操作的情況,StringBuffer:適用多線程下在字符緩沖區(qū)進(jìn)行大量操作的情況。

面試官:為什么String的是不可變的?

小宅:因為存儲數(shù)據(jù)的char數(shù)組是使用final進(jìn)行修飾的,所以不可變。

String、String Builder、String Buffer的區(qū)別是什么

面試官:剛才說到String是不可變,但是下面的代碼運(yùn)行完,卻發(fā)生變化了,這是為啥呢?
public class Demo {

    public static void main(String[] args) {
        String str = "不一樣的";
        str = str + "科技宅";
        System.out.println(str);
    }

}

很明顯上面運(yùn)行的結(jié)果是:不一樣的科技宅。

我們先使用javac Demo.class 進(jìn)行編譯,然后反編譯javap -verbose Demo 得到如下結(jié)果:

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: ldc           #2                  // String 不一樣的
         2: astore_1
         3: new           #3                  // class java/lang/StringBuilder
         6: dup
         7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        10: aload_1
        11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        14: ldc           #6                  // String 科技宅
        16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        22: astore_1
        23: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
        26: aload_1
        27: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        30: return

??我們可以發(fā)現(xiàn),在使用+ 進(jìn)行拼接的時候,實(shí)際上jvm是初始化了一個StringBuilder進(jìn)行拼接的。相當(dāng)于編譯后的代碼如下:

public class Demo {

    public static void main(String[] args) {
        String str = "不一樣的";
        StringBuilder builder =new StringBuilder();
        builder.append(str);
        builder.append("科技宅");
        str = builder.toString();
        System.out.println(str);
    }

}

我們可以看下builder.toString(); 的實(shí)現(xiàn)。

@Override
public String toString() {
  // Create a copy, don't share the array
  return new String(value, 0, count);
}

??很明顯toString方法是生成了一個新的String對象而不是更改舊的str的內(nèi)容,相當(dāng)于把舊str的引用指向的新的String對象。這也就是str發(fā)生變化的原因。

分享我碰到過的一道面試題,大家可以猜猜答案是啥?文末有解析哦

public class Demo {

    public static void main(String[] args) {
        String str = null;
        str = str + "";
        System.out.println(str);
    }

}
面試官:String類可以被繼承嘛?

小宅:不可以,因為String類使用final關(guān)鍵字進(jìn)行修飾,所以不能被繼承,并且StringBuilder,StringBuffer也是如此都被final關(guān)鍵字修飾。

面試官:為什么String Buffer是線程安全的?

小宅:這是因為在StringBuffer類內(nèi),常用的方法都使用了synchronized 進(jìn)行同步所以是線程安全的,然而StringBuilder并沒有。這也就是運(yùn)行速度StringBuilder > StringBuffer的原因了。

String、String Builder、String Buffer的區(qū)別是什么

面試官:剛才你說到了synchronized關(guān)鍵字 ,那能講講synchronized的表現(xiàn)形式嘛?

小宅

  • 對于普通同步方法 ,鎖是當(dāng)前實(shí)例對象。

  • 對于靜態(tài)同步方法,鎖是當(dāng)前類的class對象。

  • 對于同步方法塊,鎖是Synchonized括號配置的對象。

面試官:能講講synchronized的原理嘛?

小宅synchronized是一個重量級鎖,實(shí)現(xiàn)依賴于JVMmonitor 監(jiān)視器鎖。主要使用monitorentermonitorexit指令來實(shí)現(xiàn)方法同步和代碼塊同步。在編譯的是時候,會將monitorexit指令插入到同步代碼塊的開始位置,而monitorexit插入方法結(jié)束處和異常處,并且每一個monitorexit都有一個與之對應(yīng)的monitorexit。

??任何對象都有一個monitor與之關(guān)聯(lián),當(dāng)一個monitor被持有后,它將被處于鎖定狀態(tài),線程執(zhí)行到monitorenter指令時間,會嘗試獲取對象所對應(yīng)的monitor的所有權(quán),即獲取獲得對象的鎖,由于在編譯期會將monitorexit插入到方法結(jié)束處和異常處,所以在方法執(zhí)行完畢或者出現(xiàn)異常的情況會自動釋放鎖。

硬菜來了

面試官:前面你提到synchronized是個重量級鎖,那它的優(yōu)化有了解嘛?

String、String Builder、String Buffer的區(qū)別是什么

小宅:為了減少獲得鎖和和釋放鎖帶來的性能損耗引入了偏向鎖、輕量級鎖、重量級鎖來進(jìn)行優(yōu)化,鎖升級的過程如下:

??首先是一個無鎖的狀態(tài),當(dāng)線程進(jìn)入同步代碼塊的時候,會檢查對象頭內(nèi)和棧幀中的鎖記錄里是否存入存入當(dāng)前線程的ID,如果沒有使用CAS 進(jìn)行替換。以后該線程進(jìn)入和退出同步代碼塊不需要進(jìn)行CAS 操作來加鎖和解鎖,只需要判斷對象頭的Mark word內(nèi)是否存儲指向當(dāng)前線程的偏向鎖。如果有表示已經(jīng)獲得鎖,如果沒有或者不是,則需要使用CAS進(jìn)行替換,如果設(shè)置成功則當(dāng)前線程持有偏向鎖,反之將偏向鎖進(jìn)行撤銷并升級為輕量級鎖。

??輕量級鎖加鎖過程,線程在執(zhí)行同步塊之前,JVM會在當(dāng)前線程的棧幀中創(chuàng)建用于存儲鎖記錄的空間,并將對象頭的Mark Word復(fù)制到鎖記錄(Displaced Mark Word)中,然后線程嘗試使用CAS 將對象頭中的Mark Word替換為指向鎖記錄的指針。如果成功,當(dāng)前線程獲得鎖,反之表示其他線程競爭鎖,當(dāng)前線程便嘗試使用自旋來獲得鎖。

??輕量級鎖解鎖過程,解鎖時,會使用CAS將Displaced Mark Word替換回到對象頭,如果成功,則表示競爭沒有發(fā)生,反之則表示當(dāng)前鎖存在競爭鎖就會膨脹成重量級鎖。

升級過程流程圖

String、String Builder、String Buffer的區(qū)別是什么

白話一下:

??可能上面的升級過程和升級過程圖,有點(diǎn)難理解并且還有點(diǎn)繞。我們先可以了解下為什么會有鎖升級這個過程?HotSpot的作者經(jīng)過研究發(fā)現(xiàn),大多數(shù)情況下鎖不僅不存在多線程競爭,而且總是由同一個線程多次獲得。為了避免獲得鎖和和釋放鎖帶來的性能損耗引入鎖升級這樣一個過程。理解鎖升級這個流程需要明確一個點(diǎn):發(fā)生了競爭才鎖會進(jìn)行升級并且不能降級。

??我們以兩個線程T1,T2執(zhí)行同步代碼塊來演示鎖是如何膨脹起來的。我們從無鎖的狀態(tài)開始 ,這個時候T1進(jìn)入了同步代碼塊,判斷當(dāng)前鎖的一個狀態(tài)。發(fā)現(xiàn)是一個無鎖的狀態(tài),這個時候會使用CAS將鎖記錄內(nèi)的線程Id指向T1并從無鎖狀態(tài)變成了偏向鎖。運(yùn)行了一段時間后T2進(jìn)入了同步代碼塊,發(fā)現(xiàn)已經(jīng)是偏向鎖了,于是嘗試使用CAS去嘗試將鎖記錄內(nèi)的線程Id改為T2,如果更改成功則T2持有偏向鎖。失敗了說明存在競爭就升級為輕量級鎖了。

??可能你會有疑問,為啥會失敗呢?我們要從CAS操作入手,CAS是Compare-and-swap(比較與替換)的簡寫,是一種有名的無鎖算法。CAS需要有3個操作數(shù),內(nèi)存地址V,舊的預(yù)期值A(chǔ),即將要更新的目標(biāo)值B,換句話說就是,內(nèi)存地址0x01存的是數(shù)字6我想把他變成7。這個時候我先拿到0x01的值是6,然后再一次獲取0x01的值并判斷是不是6,如果是就更新為7,如果不是就再來一遍之道成功為止。這個主要是由于CPU的時間片原因,可能執(zhí)行到一半被掛起了,然后別的線程把值給改了,這個時候程序就可能將錯誤的值設(shè)置進(jìn)去,導(dǎo)致結(jié)果異常。

??簡單了解了一下CAS現(xiàn)在讓我們繼續(xù)回到鎖升級這個過程,T2嘗試使用CAS進(jìn)行替換鎖記錄內(nèi)的線程ID,結(jié)果CAS失敗了這也就意味著,這個時候T1搶走了原本屬于T2的鎖,很明顯這一刻發(fā)生了競爭所以鎖需要升級。在升級為輕量級鎖前,持有偏向鎖的線程T1會被暫停,并檢查T1的狀態(tài),如果T1處于未活動的狀態(tài)/已經(jīng)退出同步代碼塊的時候,T1會釋放偏向鎖并被喚醒。如果未退出同步代碼塊,則這個時候會升級為輕量級鎖,并且由T1獲得鎖,從安全點(diǎn)繼續(xù)執(zhí)行,執(zhí)行完后對輕量級鎖進(jìn)行釋放。

??偏向鎖的使用了出現(xiàn)競爭了才釋放鎖的機(jī)制,所以當(dāng)其他線程嘗試競爭偏向鎖時,持有偏向鎖的線程才會釋放鎖。并且偏向鎖的撤銷需要等待全局安全點(diǎn)(這個時間點(diǎn)沒有任何正在執(zhí)行的字節(jié)碼)。

??T1由于沒有人競爭經(jīng)過一段時間的平穩(wěn)運(yùn)行,在某一個時間點(diǎn)時候T2進(jìn)來了,產(chǎn)生使用CAS獲得鎖,但是發(fā)現(xiàn)失敗了,這個時候T2會等待一下(自旋獲得鎖),由于競爭不是很激烈所以等T1執(zhí)行完后,就能獲取到鎖并進(jìn)行執(zhí)行。如果長時間獲取不到鎖則就可能發(fā)生競爭了,可能出現(xiàn)了個T3把原本屬于T2的輕量級鎖給搶走了,這個時候就會升級成重量級鎖了。

String、String Builder、String Buffer的區(qū)別是什么

吃完撤退

面試官:內(nèi)心OS:竟然沒問倒他,看來讓他培訓(xùn)是沒啥希望了,讓他回去等通知吧 。

??小宅是吧,你的水平我這邊基本了解了,我對你還是比較滿意的,但是我們這邊還有幾個候選人還沒面試,沒辦法直接給你答復(fù),你先回去等通知吧。

小宅:好的好的,謝謝面試官,我這邊先回去了。多虧我準(zhǔn)備的充分,全回答上來了,應(yīng)該能收到offer了吧。

String、String Builder、String Buffer的區(qū)別是什么

面試題解析

public class Demo {

    public static void main(String[] args) {
        String str = null;
        str = str + "";
        System.out.println(str);
    }

}

答案是 null,從之前我們了解到使用+進(jìn)行拼接實(shí)際上是會轉(zhuǎn)換為StringBuilder使用append方法進(jìn)行拼接。所以我們看看append方法實(shí)現(xiàn)邏輯就明白了。

public AbstractStringBuilder append(String str) {
  if (str == null)
    return appendNull();
  int len = str.length();
  ensureCapacityInternal(count + len);
  str.getChars(0, len, value, count);
  count += len;
  return this;
}
private AbstractStringBuilder appendNull() {
  int c = count;
  ensureCapacityInternal(c + 4);
  final char[] value = this.value;
  value[c++] = 'n';
  value[c++] = 'u';
  value[c++] = 'l';
  value[c++] = 'l';
  count = c;
  return this;
}

從代碼中可以發(fā)現(xiàn),如果傳入的字符串是null時,調(diào)用appendNull方法,而appendNull會返回null。

到此,相信大家對“String、String Builder、String Buffer的區(qū)別是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

當(dāng)前名稱:String、StringBuilder、StringBuffer的區(qū)別是什么
鏈接地址:http://chinadenli.net/article18/jsicdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司標(biāo)簽優(yōu)化、用戶體驗網(wǎng)站收錄、手機(jī)網(wǎng)站建設(shè)、ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計公司
亚洲精品成人综合色在线| 丰满人妻熟妇乱又伦精另类视频| 男人和女人黄 色大片| 欧美乱码精品一区二区三| 少妇丰满a一区二区三区| 亚洲专区中文字幕在线| 中文字幕乱码一区二区三区四区| 国产欧美日韩精品自拍| 亚洲一区二区福利在线| 国产成人午夜福利片片| 色无极东京热男人的天堂| 开心久久综合激情五月天| 欧美一区二区口爆吞精| 青草草在线视频免费视频| 五月天综合网五月天综合网| 日韩精品中文在线观看| 国产内射一级二级三级| 欧美中文字幕一区在线| 国产麻豆一线二线三线| 欧美自拍偷自拍亚洲精品| 国产一级一片内射视频在线| 99久久人妻精品免费一区| 国产免费自拍黄片免费看| 欧美黑人在线精品极品| 国内女人精品一区二区三区| 国产盗摄精品一区二区视频| 欧美午夜一区二区福利视频| 国产真人无遮挡免费视频一区| 日本特黄特色大片免费观看| 经典欧美熟女激情综合网| 国产精欧美一区二区三区久久| 久久99爱爱视频视频| 亚洲欧美日韩色图七区| 亚洲午夜精品视频观看| 国产成人在线一区二区三区 | 国产精品日韩精品最新| 日韩成人动画在线观看| 日本欧美三级中文字幕| 欧美日韩成人在线一区| 日韩精品亚洲精品国产精品| 极品少妇嫩草视频在线观看|