<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          高效使用內(nèi)存,這些你得知道

          共 7439字,需瀏覽 15分鐘

           ·

          2021-04-01 14:11

          ?

          之后更新文章的頻率會(huì)變高,不過可能不會(huì)只更新技術(shù)文章了

          最近也在閱讀“金字塔原理“和”高效能人士的七個(gè)習(xí)慣“這兩本書,之后也會(huì)做個(gè)讀書心得分享

          ?

          前言

          首先有一個(gè)結(jié)論:

          「減少堆內(nèi)存的使用可以更高效使用內(nèi)存」

          ?

          這句話怎么理解呢?

          ?

          堆內(nèi)存用的越少,堆被填滿的幾率就越低,新生代回 收的次數(shù)更少,對(duì)象的晉升年齡也就不會(huì)很頻繁地增加,這意味著對(duì)象被提升到老年代的 可能性也降低了,因此, Full GC會(huì)減少,降低了GC發(fā)生的頻率

          「下面將介紹幾種減少內(nèi)存使用的方式」

          減少對(duì)象大小

          對(duì)象會(huì)占用一定數(shù)量的堆內(nèi)存,所以要減少內(nèi)存使用,最簡單的方式就是讓對(duì)象小一些

          減少對(duì)象大小有兩種方式:減少實(shí)例變量的個(gè)數(shù),或者減少實(shí)例變量的大小

          注意這里的減少變量大小主要是對(duì)每個(gè)對(duì)象選擇更小的類型,避免空間的浪費(fèi)

          「同時(shí)對(duì)于對(duì)象大小的計(jì)算,有幾個(gè)注意點(diǎn):」

          1.對(duì)象大小未必和你計(jì)算的一樣,因?yàn)閷?duì)象會(huì)被填充到 8 字節(jié)的整數(shù)倍

          2.對(duì)象內(nèi)部即使為 null 的實(shí)例變量也會(huì)占用空間

          延遲初始化

          有時(shí)候需要采用延遲初始化來降低初始化類和創(chuàng)建對(duì)象的開銷

          注意我們一般不會(huì)在線程安全的代碼上引入延遲初始化,這樣會(huì)增加同步操作的開銷

          同時(shí)對(duì)于使用了線程安全對(duì)象的代碼,如果要采用延遲初始化,也應(yīng)該使用雙重檢查鎖,比如大家熟悉的單例的寫法:

          public class LazyDoubleCheckSingleton {
              private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;

              private LazyDoubleCheckSingleton(){

              }

              public static LazyDoubleCheckSingleton getInstance() {
                  if (lazyDoubleCheckSingleton == null) {
                      synchronized (LazyDoubleCheckSingleton.class{
                          if (lazyDoubleCheckSingleton == null) {
                              lazyDoubleCheckSingleton =  new LazyDoubleCheckSingleton();
                          }
                      }
                  }
                  return lazyDoubleCheckSingleton;
              }
          }

          「盡早清理空值數(shù)據(jù)」

          延遲初始化的對(duì)象如果一直不用的話,通過將變量的值設(shè)置為 null ,實(shí)現(xiàn)盡早清理, 從而使對(duì)象可以更快地被垃圾收集器回收

          可以看看JDK 中 ArrayList 類的 remove() 方法的實(shí)現(xiàn):

          public E remove(int index) {
                  //檢查下標(biāo)是否越界
                  rangeCheck(index);

                  modCount++;
                  E oldValue = elementData(index);

                  //將index+1以及之后的元素向前移動(dòng)以為,覆蓋被刪除的值
                  int numMoved = size - index - 1;
                  if (numMoved > 0)
                      System.arraycopy(elementData, index+1, elementData, index,
                                       numMoved);
                  //將最后一個(gè)位置的元素清空
                  elementData[--size] = null// clear to let GC do its work

                  return oldValue;
              }

          關(guān)鍵就是對(duì)于不需要再引用的元素,應(yīng)該主動(dòng)將其設(shè)置為 null

          不可變對(duì)象

          「使用不可變的對(duì)象常量可以很好的減少空間的浪費(fèi)」

          在 Java 中,很多對(duì)象類型都是不可變的

          包括那些有相應(yīng)的基本類型的類,如 Integer 、 Double 和 Boolean 等, 以及其他一些基于數(shù)值的類型, 如 BigDecimal

          最常見的 Java 對(duì)象當(dāng)屬不可變的 String

          「舉個(gè)Boolean類的例子說說」

          在 Java 中,其實(shí)只需要兩個(gè) Boolean 示例,一個(gè)表 示 true , 一個(gè)表示 false

          Boolean 類有一個(gè) public 的構(gòu)造 器,應(yīng)用喜歡創(chuàng)建多少這類對(duì)象就能創(chuàng)建多少,即使它們和兩個(gè)Boolean 對(duì)象其 中之一是完全相同的

          更好的設(shè)計(jì)方案應(yīng)該是,讓 Boolean 類只有一個(gè) private 的構(gòu)造器, 通過 static 方法根據(jù)其參數(shù)返回 Boolean.TRUEBoolean.FALSE ,就可以防止它們占用應(yīng)用中額外的堆空間

          public static final Boolean TRUE = new Boolean(true);

          public static final Boolean FALSE = new Boolean(false);

          字符串常量池

          字符串是最常見的 Java 對(duì)象;應(yīng)用的堆中幾乎到處都是字符串

          如果有大量的字符串是相同的,那很大一部分空間都是浪費(fèi)的

          「所以有了字符串常量池的概念」

          我們知道String 常見的創(chuàng)建方式有兩種,new String() 的方式和直接賦值的方式

          直接賦值的方式會(huì)先去字符串常量池中查找是否已經(jīng)有此值,如果有則把引用地址直接指向此值,否則會(huì)先在常量池中創(chuàng)建,然后再把引用指向此值;而 new String()的方式一定會(huì)先在堆上創(chuàng)建一個(gè)字符串對(duì)象,然后再去常量池中查詢此字符串的值是否已經(jīng)存在,如果不存在會(huì)先在常量池中創(chuàng)建此字符串,然后把引用的值指向此字符串

          String s1 = new String("Java");
          String s2 = s1.intern();
          String s3 = "Java";
          System.out.println(s1 == s2); // false
          System.out.println(s2 == s3); // true

          除此之外編譯器還會(huì)對(duì) String 字符串做一些優(yōu)化,例如以下代碼:

          String s1 = "Ja" + "va";
          String s2 = "Java";
          System.out.println(s1 == s2);

          雖然 s1 拼接了多個(gè)字符串,但對(duì)比的結(jié)果卻是 true,我們使用反編譯工具,看到的結(jié)果如下:

          Compiled from "StringExample.java"
          public class com.lagou.interview.StringExample {
            public com.lagou.interview.StringExample();
              Code:
                 0: aload_0
                 1: invokespecial #1                  // Method java/lang/Object."<init>":()V
                 4return
              LineNumberTable:
                line 30

            public static void main(java.lang.String[]);
              Code:
                 0: ldc           #2                  // String Java
                 2: astore_1
                 3: ldc           #2                  // String Java
                 5: astore_2
                 6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
                 9: aload_1
                10: aload_2
                11: if_acmpne     18
                14: iconst_1
                15goto          19
                18: iconst_0
                19: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
                22return
              LineNumberTable:
                line 50
                line 63
                line 76
                line 822
          }

          從編譯代碼 #2 可以看出,代碼 “Ja”+”va” 被直接編譯成了 “Java” ,因此 s1==s2 的結(jié)果才是 true,這就是編譯器對(duì)字符串優(yōu)化的結(jié)果

          最后

          「喜歡的話,希望幫忙點(diǎn)贊,轉(zhuǎn)發(fā)下哈,謝謝」

          微信搜索:月伴飛魚,交個(gè)朋友

          公眾號(hào)后臺(tái)回復(fù)666,獲得免費(fèi)電子書籍,必讀書籍這里全都有

          參考:

          • 書籍:Java性能權(quán)威指南

          社招一年半面經(jīng)分享(含阿里美團(tuán)頭條京東滴滴)


          條件語句的多層嵌套問題優(yōu)化,助你寫出不讓同事吐槽的代碼


          寫出好的Join語句,前提你得懂這些

          瀏覽 28
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产女人操逼视频 | 色一色撸一撸 | 欧美色图另类图片 | 黄色视频日韩 | 日韩A ⅴ|