欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中字符串去重的特性介紹

 更新時(shí)間:2015年07月10日 10:18:36   投稿:goldensun  
這篇文章主要介紹了Java中字符串去重的特性,是Java8中引入的一個(gè)新特性,至于是否真的用起來(lái)順手就見(jiàn)仁見(jiàn)智了...需要的朋友可以參考下

字符串在任何應(yīng)用中都占用了大量的內(nèi)存。尤其數(shù)包含獨(dú)立UTF-16字符的char[]數(shù)組對(duì)JVM內(nèi)存的消耗貢獻(xiàn)最多——因?yàn)槊總€(gè)字符占用2位。

內(nèi)存的30%被字符串消耗其實(shí)是很常見(jiàn)的,不僅是因?yàn)樽址桥c我們互動(dòng)的最好的格式,而且是由于流行的HTTP API使用了大量的字符串。使用Java 8 Update 20,我們現(xiàn)在可以接觸到一個(gè)新特性,叫做字符串去重,該特性需要G1垃圾回收器,該垃圾回收器默認(rèn)是被關(guān)閉的。

字符串去重利用了字符串內(nèi)部實(shí)際是char數(shù)組,并且是final的特性,所以JVM可以任意的操縱他們。


對(duì)于字符串去重,開(kāi)發(fā)者考慮了大量的策略,但最終的實(shí)現(xiàn)采用了下面的方式:

無(wú)論何時(shí)垃圾回收器訪問(wèn)了String對(duì)象,它會(huì)對(duì)char數(shù)組進(jìn)行一個(gè)標(biāo)記。它獲取char數(shù)組的hash value并把它和一個(gè)對(duì)數(shù)組的弱引用存在一起。只要垃圾回收器發(fā)現(xiàn)另一個(gè)字符串,而這個(gè)字符串和char數(shù)組具有相同的hash code,那么就會(huì)對(duì)兩者進(jìn)行一個(gè)字符一個(gè)字符的比對(duì)。

如果他們恰好匹配,那么一個(gè)字符串就會(huì)被修改,指向第二個(gè)字符串的char數(shù)組。第一個(gè)char數(shù)組就不再被引用,也就可以被回收了。

這整個(gè)過(guò)程當(dāng)然帶來(lái)了一些開(kāi)銷,但是被很緊實(shí)的上限控制了。例如,如果一個(gè)字符未發(fā)現(xiàn)有重復(fù),那么一段時(shí)間之內(nèi),它會(huì)不再被檢查。


那么該特性實(shí)際上是怎么工作的呢?首先,你需要?jiǎng)倓偘l(fā)布的Java 8 Update 20,然后按照這個(gè)配置: -Xmx256m -XX:+UseG1GC 去運(yùn)行下列的代碼:
 

public class LotsOfStrings {
 
 private static final LinkedList<String> LOTS_OF_STRINGS = new LinkedList<>();
 
 public static void main(String[] args) throws Exception {
  int iteration = 0;
  while (true) {
   for (int i = 0; i < 100; i++) {
    for (int j = 0; j < 1000; j++) {
     LOTS_OF_STRINGS.add(new String("String " + j));
    }
   }
   iteration++;
   System.out.println("Survived Iteration: " + iteration);
   Thread.sleep(100);
  }
 }
}

這段代碼會(huì)執(zhí)行30個(gè)迭代之后報(bào)OutOfMemoryError。

現(xiàn)在,開(kāi)啟字符串去重,使用如下配置去跑上述代碼:

-Xmx256m -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics

此時(shí)它已經(jīng)可以運(yùn)行更長(zhǎng)的時(shí)間,而且在50個(gè)迭代之后才終止。

JVM現(xiàn)在同樣打印出了它做了什么,讓我們一起看一下:

 

[GC concurrent-string-deduplication, 4658.2K->0.0B(4658.2K), avg 99.6%, 0.0165023 secs]
  [Last Exec: 0.0165023 secs, Idle: 0.0953764 secs, Blocked: 0/0.0000000 secs]
   [Inspected:     119538]
     [Skipped:       0( 0.0%)]
     [Hashed:     119538(100.0%)]
     [Known:        0( 0.0%)]
     [New:       119538(100.0%)  4658.2K]
   [Deduplicated:    119538(100.0%)  4658.2K(100.0%)]
     [Young:       372( 0.3%)   14.5K( 0.3%)]
     [Old:       119166( 99.7%)  4643.8K( 99.7%)]
  [Total Exec: 4/0.0802259 secs, Idle: 4/0.6491928 secs, Blocked: 0/0.0000000 secs]
   [Inspected:     557503]
     [Skipped:       0( 0.0%)]
     [Hashed:     556191( 99.8%)]
     [Known:       903( 0.2%)]
     [New:       556600( 99.8%)   21.2M]
   [Deduplicated:    554727( 99.7%)   21.1M( 99.6%)]
     [Young:       1101( 0.2%)   43.0K( 0.2%)]
     [Old:       553626( 99.8%)   21.1M( 99.8%)]
  [Table]
   [Memory Usage: 81.1K]
   [Size: 2048, Min: 1024, Max: 16777216]
   [Entries: 2776, Load: 135.5%, Cached: 0, Added: 2776, Removed: 0]
   [Resize Count: 1, Shrink Threshold: 1365(66.7%), Grow Threshold: 4096(200.0%)]
   [Rehash Count: 0, Rehash Threshold: 120, Hash Seed: 0x0]
   [Age Threshold: 3]
  [Queue]
   [Dropped: 0]

為了方便,我們不需要自己去計(jì)算所有數(shù)據(jù)的加和,使用方便的總計(jì)就可以了。

上面的代碼段規(guī)定執(zhí)行了字符串去重,花了16ms的時(shí)間,查看了約 120 k 字符串。


上面的特性是剛推出的,意味著可能并沒(méi)有被全面的審視。具體的數(shù)據(jù)在實(shí)際的應(yīng)用中可能看起來(lái)有差別,尤其是那些應(yīng)用中字符串被多次使用和傳遞,因此一些字符串可能被跳過(guò)或者早就有了hashcode(正如你可能知道的那樣,一個(gè)String的hash code是被懶加載的)。

在上述的案例中,所有的字符串都被去重了,在內(nèi)存中移除了4.5MB的數(shù)據(jù)。

[Table]部分給出了有關(guān)內(nèi)部跟蹤表的統(tǒng)計(jì)信息,[Queue]則列出了有多少對(duì)去重的請(qǐng)求由于負(fù)載被丟棄,這也是開(kāi)銷減少機(jī)制中的一部分。

那么,字符串去重和字符串駐留相比又有什么差別呢?事實(shí)上,字符串去重和駐留看起來(lái)差不多,除了暫留的機(jī)制重用了整個(gè)字符串實(shí)例,而不僅僅是字符數(shù)組。


JDK Enhancement Proposal 192的創(chuàng)造者的爭(zhēng)論點(diǎn)在于開(kāi)發(fā)者們常常不知道將駐留字符串放在哪里合適,或者是合適的地方被框架所隱藏.就像我寫(xiě)的那樣,當(dāng)碰到復(fù)制字符串(像國(guó)家名字)的時(shí)候,你需要一些常識(shí).字符串去重,對(duì)于在同一個(gè)JVM中的應(yīng)用程序的字符串復(fù)制也有好處,同樣包括像XML Schemas,urls以及jar名字等一般認(rèn)為不會(huì)出現(xiàn)多次的字符串.

當(dāng)字符串駐留發(fā)生在應(yīng)用程序線程中的時(shí)候,垃圾回收異步并發(fā)處理時(shí),字符串去重也不會(huì)增加運(yùn)行時(shí)的消耗.這也解釋了,為什么我們會(huì)在上面的代碼中發(fā)現(xiàn)Thread.sleep().如果沒(méi)有sleep會(huì)給GC增加太多的壓力,這樣字符串去重根本就不會(huì)發(fā)生.但是,這只是示例代碼才會(huì)出現(xiàn)的問(wèn)題.實(shí)際的應(yīng)用程序,常常會(huì)在運(yùn)行字符串去重的時(shí)候使用幾毫秒的時(shí)間.

相關(guān)文章

  • IntelliJ IDEA(2017)安裝和破解的方法

    IntelliJ IDEA(2017)安裝和破解的方法

    這篇文章主要介紹了IntelliJ IDEA(2017)安裝和破解的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • SpringBoot中Zookeeper分布式鎖的原理和用法詳解

    SpringBoot中Zookeeper分布式鎖的原理和用法詳解

    Zookeeper是一個(gè)分布式協(xié)調(diào)服務(wù),它提供了高可用、高性能、可擴(kuò)展的分布式鎖機(jī)制,SpringBoot是一個(gè)基于Spring框架的開(kāi)發(fā)框架,它提供了對(duì)Zookeeper分布式鎖的集成支持,本文將介紹SpringBoot中的 Zookeeper分布式鎖的原理和使用方法,需要的朋友可以參考下
    2023-07-07
  • java中File類的構(gòu)造函數(shù)及其方法

    java中File類的構(gòu)造函數(shù)及其方法

    這篇文章主要介紹了java中File類的構(gòu)造函數(shù)及其方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-06-06
  • Spring Boot與React集成的示例代碼

    Spring Boot與React集成的示例代碼

    這篇文章主要介紹了Spring Boot與React集成的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • Java代碼中如何設(shè)置輸出字符集為UTF-8

    Java代碼中如何設(shè)置輸出字符集為UTF-8

    這篇文章主要介紹了Java代碼中設(shè)置輸出字符集為UTF-8,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • idea中如何使用git進(jìn)行版本回退詳解

    idea中如何使用git進(jìn)行版本回退詳解

    工作中遇到git遠(yuǎn)程倉(cāng)庫(kù)需要回退到歷史版本的問(wèn)題,根據(jù)網(wǎng)上的搜索結(jié)果結(jié)合自己的實(shí)踐,下面這篇文章主要給大家介紹了關(guān)于idea中如何使用git進(jìn)行版本回退的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • 使用ObjectMapper把Json轉(zhuǎn)換為復(fù)雜的實(shí)體類

    使用ObjectMapper把Json轉(zhuǎn)換為復(fù)雜的實(shí)體類

    這篇文章主要介紹了使用ObjectMapper把Json轉(zhuǎn)換為復(fù)雜的實(shí)體類操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java random.nextInt的坑及解決

    java random.nextInt的坑及解決

    這篇文章主要介紹了java random.nextInt的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Spring AOP定義AfterReturning增加實(shí)例分析

    Spring AOP定義AfterReturning增加實(shí)例分析

    這篇文章主要介紹了Spring AOP定義AfterReturning增加,結(jié)合實(shí)例形式分析了Spring面相切面AOP定義AfterReturning增加相關(guān)操作技巧與使用注意事項(xiàng),需要的朋友可以參考下
    2020-01-01
  • JDK反序列化時(shí)修改類的全限定性名解析

    JDK反序列化時(shí)修改類的全限定性名解析

    這篇文章主要介紹了JDK反序列化時(shí)修改類的全限定性名解析,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12

最新評(píng)論