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

通過(guò)Java代碼技巧改善性能

 更新時(shí)間:2019年05月31日 08:28:48   投稿:laozhang  
在本篇文章里小編給大家分享了關(guān)于通過(guò)Java代碼技巧改善性能的相關(guān)知識(shí)點(diǎn),需要的朋友們參考下。

前言

程序的性能受到代碼質(zhì)量的直接影響。這次主要介紹一些代碼編寫的小技巧和慣例。雖然看起來(lái)有些是微不足道的編程技巧,卻可能為系統(tǒng)性能帶來(lái)成倍的提升,因此還是值得關(guān)注的。

慎用異常

在Java開(kāi)發(fā)中,經(jīng)常使用try-catch進(jìn)行錯(cuò)誤捕獲,但是try-catch語(yǔ)句對(duì)系統(tǒng)性能而言是非常糟糕的。雖然一次try-catch中,無(wú)法察覺(jué)到她對(duì)性能帶來(lái)的損失,但是一旦try-catch語(yǔ)句被應(yīng)用于循環(huán)或是遍歷體內(nèi),就會(huì)給系統(tǒng)性能帶來(lái)極大的傷害。

以下是一段將try-catch應(yīng)用于循環(huán)體內(nèi)的示例代碼:

@Test
  public void test11() {

    long start = System.currentTimeMillis();
    int a = 0;
    for(int i=0;i<1000000000;i++){
      try {
        a++;
      }catch (Exception e){
        e.printStackTrace();
      }
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);

  }

上面這段代碼運(yùn)行結(jié)果是:

useTime:10

下面是一段將try-catch移到循環(huán)體外的代碼,那么性能就提升了將近一半。如下:

@Test
  public void test(){
    long start = System.currentTimeMillis();
    int a = 0;
    try {
      for (int i=0;i<1000000000;i++){
        a++;
      }
    }catch (Exception e){
      e.printStackTrace();
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println(useTime);
  }

運(yùn)行結(jié)果:

useTime:6

使用局部變量

調(diào)用方法時(shí)傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時(shí)變量都保存在棧(Stack)中,速度快。其他變量,如靜態(tài)變量、實(shí)例變量等,都在堆(Heap)中創(chuàng)建,速度較慢。

下面是一段使用局部變量進(jìn)行計(jì)算的代碼:

@Test
  public void test11() {

    long start = System.currentTimeMillis();
    int a = 0;
    for(int i=0;i<1000000000;i++){
      a++;
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);

  }

運(yùn)行結(jié)果:

useTime:5

將局部變量替換為類的靜態(tài)變量:

static int aa = 0;
  @Test
  public void test(){
    long start = System.currentTimeMillis();

    for (int i=0;i<1000000000;i++){
      aa++;
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);
  }

運(yùn)行結(jié)果:

useTime:94

通過(guò)上面兩次的運(yùn)行結(jié)果,可以看出來(lái)局部變量的訪問(wèn)速度遠(yuǎn)遠(yuǎn)高于類成員變量。

位運(yùn)算代替乘除法

在所有的運(yùn)算中,位運(yùn)算是最為高效的。因此,可以嘗試使用位運(yùn)算代替部分算術(shù)運(yùn)算,來(lái)提高系統(tǒng)的運(yùn)行速度。最典型的就是對(duì)于整數(shù)的乘除運(yùn)算優(yōu)化。

下面是一段使用算術(shù)運(yùn)算的代碼:

@Test
  public void test11() {

    long start = System.currentTimeMillis();
    int a = 0;
    for(int i=0;i<1000000000;i++){
      a*=2;
      a/=2;
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);
  }

運(yùn)行結(jié)果:

useTime:1451

將循環(huán)體中的乘除運(yùn)算改為等價(jià)的位運(yùn)算,代碼如下:

@Test
  public void test(){
    long start = System.currentTimeMillis();
    int aa = 0;
    for (int i=0;i<1000000000;i++){
      aa<<=1;
      aa>>=1;
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);
  }

運(yùn)行結(jié)果:

useTime:10

上兩段代碼執(zhí)行了完全相同的功能,在每次循環(huán)中,都將整數(shù)乘以2,并除以2。但是運(yùn)行結(jié)果耗時(shí)相差非常大,所以位運(yùn)算的效率還是顯而易見(jiàn)的。

提取表達(dá)式

在軟件開(kāi)發(fā)過(guò)程中,程序員很容易有意無(wú)意地讓代碼做一些“重復(fù)勞動(dòng)”,在大部分情況下,由于計(jì)算機(jī)的高速運(yùn)行,這些“重復(fù)勞動(dòng)”并不會(huì)對(duì)性能構(gòu)成太大的威脅,但若希望將系統(tǒng)性能發(fā)揮到極致,提取這些“重復(fù)勞動(dòng)”相當(dāng)有意義。

比如以下代碼中進(jìn)行了兩次算術(shù)計(jì)算:

@Test
  public void testExpression(){
    long start = System.currentTimeMillis();
    double d = Math.random();
    double a = Math.random();
    double b = Math.random();
    double e = Math.random();

    double x,y;
    for(int i=0;i<10000000;i++){
      x = d*a*b/3*4*a;
      y = e*a*b/3*4*a;
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);

  }

運(yùn)行結(jié)果:

useTime:21

仔細(xì)看能發(fā)現(xiàn),兩個(gè)計(jì)算表達(dá)式的后半部分完全相同,這也意味著在每次循環(huán)中,相同部分的表達(dá)式被重新計(jì)算了。

那么改進(jìn)一下后就變成了下面的樣子:

@Test
  public void testExpression99(){
    long start = System.currentTimeMillis();
    double d = Math.random();
    double a = Math.random();
    double b = Math.random();
    double e = Math.random();

    double p,x,y;
    for(int i=0;i<10000000;i++){
      p = a*b/3*4*a;
      x = d*p;
      y = e*p;
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);
  }

運(yùn)行結(jié)果:

useTime:11

通過(guò)運(yùn)行結(jié)果我們可以看出來(lái)具體的優(yōu)化效果。

同理,如果在某循環(huán)中需要執(zhí)行一個(gè)耗時(shí)操作,而在循環(huán)體內(nèi),其執(zhí)行結(jié)果總是唯一的,也應(yīng)該提取到循環(huán)體外。

例如下面的代碼:

for(int i=0;i<100000;i++){
  x[i] = Math.PI*Math.sin(y)*i;
}

應(yīng)該改進(jìn)成下面的代碼:

//提取復(fù)雜,固定結(jié)果的業(yè)務(wù)邏輯處理到循環(huán)體外
double p = Math.PI*Math.sin(y);
for(int i=0;i<100000;i++){
  x[i] = p*i;
}

使用arrayCopy()

數(shù)組復(fù)制是一項(xiàng)使用頻率很高的功能,JDK中提供了一個(gè)高效的API來(lái)實(shí)現(xiàn)它。

/**
   * @param   src   the source array.
   * @param   srcPos  starting position in the source array.
   * @param   dest   the destination array.
   * @param   destPos starting position in the destination data.
   * @param   length  the number of array elements to be copied.
   * @exception IndexOutOfBoundsException if copying would cause
   *        access of data outside array bounds.
   * @exception ArrayStoreException if an element in the <code>src</code>
   *        array could not be stored into the <code>dest</code> array
   *        because of a type mismatch.
   * @exception NullPointerException if either <code>src</code> or
   *        <code>dest</code> is <code>null</code>.
   */
  public static native void arraycopy(Object src, int srcPos,
                    Object dest, int destPos,
                    int length);

如果在應(yīng)用程序中需要進(jìn)行數(shù)組復(fù)制,應(yīng)該使用這個(gè)函數(shù),而不是自己實(shí)現(xiàn)。

下面來(lái)舉例:

@Test
  public void testArrayCopy(){
    int size = 100000;
    int[] array = new int[size];
    int[] arraydest = new int[size];

    for(int i=0;i<array.length;i++){
      array[i] = i;
    }
    long start = System.currentTimeMillis();
    for (int k=0;k<1000;k++){
      //進(jìn)行復(fù)制
      System.arraycopy(array,0,arraydest,0,size);
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);
  }

運(yùn)行結(jié)果:

useTime:59

相對(duì)應(yīng)地,如果在程序中,自己實(shí)現(xiàn)數(shù)組復(fù)制,其等價(jià)代碼如下:

@Test
  public void testArrayCopy99(){
    int size = 100000;
    int[] array = new int[size];
    int[] arraydest = new int[size];

    for(int i=0;i<array.length;i++){
      array[i] = i;
    }
    long start = System.currentTimeMillis();
    for (int k=0;k<1000;k++){
      for(int i=0;i<size;i++){
        arraydest[i] = array[i];
      }
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);
  }

運(yùn)行結(jié)果:

useTime:102

通過(guò)運(yùn)行結(jié)果可以看出效果。

因?yàn)镾ystem.arraycopy()函數(shù)是native函數(shù),通常native函數(shù)的性能要優(yōu)于普通函數(shù)。僅出于性能考慮,在程序開(kāi)發(fā)時(shí),應(yīng)盡可能調(diào)用native函數(shù)。

相關(guān)文章

  • Java中的abstract和interface

    Java中的abstract和interface

    abstract和interface關(guān)鍵字在Java中隨處可見(jiàn),它是Java三大特性封裝、繼承、多態(tài)特性的實(shí)現(xiàn)重要支柱之一。interface關(guān)鍵字用于定義接口抽象,其本質(zhì)上是用于定義類型、定義類所具有的能力,下面來(lái)看看詳細(xì)內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • Java調(diào)用SQL腳本執(zhí)行常用的方法示例

    Java調(diào)用SQL腳本執(zhí)行常用的方法示例

    這篇文章主要給大家介紹了關(guān)于Java調(diào)用SQL腳本執(zhí)行常用的方法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-04-04
  • MyBatisPlus?TypeHandler自定義字段類型轉(zhuǎn)換Handler

    MyBatisPlus?TypeHandler自定義字段類型轉(zhuǎn)換Handler

    這篇文章主要為大家介紹了MyBatisPlus?TypeHandler自定義字段類型轉(zhuǎn)換Handler示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 解決springcloud-gateway限流遇到的問(wèn)題

    解決springcloud-gateway限流遇到的問(wèn)題

    這篇文章主要介紹了解決springcloud-gateway限流遇到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java設(shè)計(jì)模式之原型模式詳細(xì)解析

    Java設(shè)計(jì)模式之原型模式詳細(xì)解析

    這篇文章主要介紹了Java設(shè)計(jì)模式之原型模式詳細(xì)解析,原型模式就是用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型,通過(guò)復(fù)制該原型對(duì)象來(lái)創(chuàng)建一個(gè)和原型對(duì)象相同的新對(duì)象,需要的朋友可以參考下
    2023-11-11
  • 通過(guò)AOP環(huán)繞通知如何實(shí)現(xiàn)事務(wù)控制

    通過(guò)AOP環(huán)繞通知如何實(shí)現(xiàn)事務(wù)控制

    這篇文章主要介紹了通過(guò)AOP環(huán)繞通知如何實(shí)現(xiàn)事務(wù)控制的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 解讀Spring定義Bean的兩種方式:<bean>和@Bean

    解讀Spring定義Bean的兩種方式:<bean>和@Bean

    這篇文章主要介紹了Spring定義Bean的兩種方式:<bean>和@Bean,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java設(shè)計(jì)模式之工廠模式(Factory模式)介紹

    Java設(shè)計(jì)模式之工廠模式(Factory模式)介紹

    這篇文章主要介紹了Java設(shè)計(jì)模式之工廠模式(Factory模式)介紹,本文講解了為何使用工廠模式、工廠方法、抽象工廠、Java工廠模式舉例等內(nèi)容,需要的朋友可以參考下
    2015-03-03
  • windows 部署JAVA環(huán)境安裝iDea的詳細(xì)步驟

    windows 部署JAVA環(huán)境安裝iDea的詳細(xì)步驟

    這篇文章主要介紹了windows 部署JAVA環(huán)境安裝iDea的詳細(xì)步驟,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 淺談String.split()遇到空字符串的幾種情況

    淺談String.split()遇到空字符串的幾種情況

    這篇文章主要介紹了淺談String.split()遇到空字符串的幾種情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10

最新評(píng)論