最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

通過Java代碼技巧改善性能

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

前言

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

慎用異常

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

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

@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);

  }

上面這段代碼運行結果是:

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);
  }

運行結果:

useTime:6

使用局部變量

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

下面是一段使用局部變量進行計算的代碼:

@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);

  }

運行結果:

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);
  }

運行結果:

useTime:94

通過上面兩次的運行結果,可以看出來局部變量的訪問速度遠遠高于類成員變量。

位運算代替乘除法

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

下面是一段使用算術運算的代碼:

@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);
  }

運行結果:

useTime:1451

將循環(huá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);
  }

運行結果:

useTime:10

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

提取表達式

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

比如以下代碼中進行了兩次算術計算:

@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);

  }

運行結果:

useTime:21

仔細看能發(fā)現,兩個計算表達式的后半部分完全相同,這也意味著在每次循環(huá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);
  }

運行結果:

useTime:11

通過運行結果我們可以看出來具體的優(yōu)化效果。

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

例如下面的代碼:

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

應該改進成下面的代碼:

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

使用arrayCopy()

數組復制是一項使用頻率很高的功能,JDK中提供了一個高效的API來實現它。

/**
   * @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);

如果在應用程序中需要進行數組復制,應該使用這個函數,而不是自己實現。

下面來舉例:

@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++){
      //進行復制
      System.arraycopy(array,0,arraydest,0,size);
    }
    long useTime = System.currentTimeMillis()-start;
    System.out.println("useTime:"+useTime);
  }

運行結果:

useTime:59

相對應地,如果在程序中,自己實現數組復制,其等價代碼如下:

@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);
  }

運行結果:

useTime:102

通過運行結果可以看出效果。

因為System.arraycopy()函數是native函數,通常native函數的性能要優(yōu)于普通函數。僅出于性能考慮,在程序開發(fā)時,應盡可能調用native函數。

相關文章

  • IDEA2023.1.3安裝教程及下載(圖文)

    IDEA2023.1.3安裝教程及下載(圖文)

    最新變化是在IDEA?2023.1中,對新UI做出了大量改進,本文主要介紹了IDEA2023.1.3安裝教程及下載,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • SpringBoot依賴及其作用分析

    SpringBoot依賴及其作用分析

    這篇文章主要介紹了SpringBoot依賴及其作用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 淺談Java為什么只能單繼承

    淺談Java為什么只能單繼承

    本文主要介紹了Java為什么只能單繼承,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • Java8生成時間方式及格式化時間的方法實例

    Java8生成時間方式及格式化時間的方法實例

    這篇文章主要給大家介紹了關于Java8生成時間方式及格式化時間的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • Mybatis流式查詢之ResultHanlde問題

    Mybatis流式查詢之ResultHanlde問題

    這篇文章主要介紹了Mybatis流式查詢之ResultHanlde問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • JAVA線程用法詳解

    JAVA線程用法詳解

    這篇文章主要介紹了JAVA線程用法,配合實例針對Java中線程的開啟、sleep、合并與讓出等進行了較為深入的分析,需要的朋友可以參考下
    2014-08-08
  • 解決springboot mapper注入報紅問題

    解決springboot mapper注入報紅問題

    這篇文章主要介紹了解決springboot mapper注入報紅問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java如何將map數據存入到實體類對象中

    java如何將map數據存入到實體類對象中

    在Java編程中,經常需要將Map集合中的數據轉換為實體類對象,這可以通過反射機制實現,即通過遍歷Map對象,使用反射根據鍵名對應實體類的屬性名,動態(tài)調用setter方法將值設置到實體對象中,這樣的操作使得數據從Map結構轉移到了具體的JavaBean中,便于后續(xù)的操作和管理
    2024-09-09
  • kotlin快速入門之標準函數與靜態(tài)方法

    kotlin快速入門之標準函數與靜態(tài)方法

    學完了Kotlin的基礎知識,是時候來來學習 Kotlin的標準函數和靜態(tài)方法了,下面這篇文章主要給大家介紹了關于kotlin快速入門之標準函數與靜態(tài)方法的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-09-09
  • Java抽象類和普通類區(qū)別、 數組跟List的區(qū)別解析

    Java抽象類和普通類區(qū)別、 數組跟List的區(qū)別解析

    這篇文章主要介紹了Java抽象類和普通類區(qū)別、 數組跟List的區(qū)別,在這里需要注意List是一個接口,不能直接實例化,需要使用具體的實現類來創(chuàng)建對象,本文結合示例代碼介紹的非常詳細,需要的朋友參考下吧
    2023-09-09

最新評論

门源| 宣武区| 象州县| 宜君县| 永定县| 双桥区| 阳曲县| 金平| 平度市| 博乐市| 湘潭市| 南丹县| 蚌埠市| 朝阳市| 高淳县| 平远县| 江西省| 正镶白旗| 上林县| 石嘴山市| 迁安市| 乐昌市| 上林县| 邯郸市| 永新县| 五大连池市| 松阳县| 达孜县| 白玉县| 揭阳市| 巴林右旗| 临沧市| 浙江省| 兰考县| 巴东县| 阿拉尔市| 洞头县| 湖口县| 伊川县| 白城市| 三明市|