日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
啪啪打臉!領(lǐng)導(dǎo)說:try-catch要放在循環(huán)體外!

今天給大家?guī)淼氖顷P(guān)于 try-catch 應(yīng)該放在循環(huán)體外,還是放在循環(huán)體內(nèi)的文章,我們將從性能和業(yè)務(wù)場景分析這兩個方面來回答此問題。

主要從事網(wǎng)頁設(shè)計、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、wap網(wǎng)站建設(shè)(手機版網(wǎng)站建設(shè))、成都響應(yīng)式網(wǎng)站建設(shè)公司、程序開發(fā)、微網(wǎng)站、重慶小程序開發(fā)公司等,憑借多年來在互聯(lián)網(wǎng)的打拼,我們在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了豐富的成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、網(wǎng)絡(luò)營銷經(jīng)驗,集策劃、開發(fā)、設(shè)計、營銷、管理等多方位專業(yè)化運作于一體,具備承接不同規(guī)模與類型的建設(shè)項目的能力。

很多人對 try-catch 有一定的誤解,比如我們經(jīng)常會把它(try-catch)和“低性能”直接畫上等號,但對 try-catch 的本質(zhì)(是什么)卻缺少著最基礎(chǔ)的了解,因此我們也會在本篇中對 try-catch 的本質(zhì)進行相關(guān)的探索。

性能評測

話不多說,我們直接來開始今天的測試,本文我們依舊使用 Oracle 官方提供的 JMH(Java Microbenchmark Harness,JAVA 微基準(zhǔn)測試套件)來進行測試。

首先在 pom.xml 文件中添加 JMH 框架,配置如下:

 
 
 
 
  1.   
  2.   
  3.    org.openjdk.jmh  
  4.    jmh-core  
  5.    {version}  
  6.  

完整測試代碼如下:

 
 
 
 
  1. import org.openjdk.jmh.annotations.*;  
  2. import org.openjdk.jmh.runner.Runner;  
  3. import org.openjdk.jmh.runner.RunnerException;  
  4. import org.openjdk.jmh.runner.options.Options;  
  5. import org.openjdk.jmh.runner.options.OptionsBuilder;  
  6. import java.util.concurrent.TimeUnit;  
  7. /**  
  8.  * try - catch 性能測試  
  9.  */  
  10. @BenchmarkMode(Mode.AverageTime) // 測試完成時間  
  11. @OutputTimeUnit(TimeUnit.NANOSECONDS)  
  12. @Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS) // 預(yù)熱 1 輪,每次 1s  
  13. @Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 測試 5 輪,每次 3s  
  14. @Fork(1) // fork 1 個線程  
  15. @State(Scope.Benchmark)  
  16. @Threads(100) 
  17. public class TryCatchPerformanceTest {  
  18.     private static final int forSize = 1000; // 循環(huán)次數(shù)  
  19.     public static void main(String[] args) throws RunnerException {  
  20.         // 啟動基準(zhǔn)測試  
  21.         Options opt = new OptionsBuilder()  
  22.                 .include(TryCatchPerformanceTest.class.getSimpleName()) // 要導(dǎo)入的測試類  
  23.                 .build();  
  24.         new Runner(opt).run(); // 執(zhí)行測試  
  25.     }  
  26.     @Benchmark  
  27.     public int innerForeach() {  
  28.         int count = 0;  
  29.         for (int i = 0; i < forSize; i++) {  
  30.             try {  
  31.                 if (i == forSize) {  
  32.                     throw new Exception("new Exception");  
  33.                 }  
  34.                 count++;  
  35.             } catch (Exception e) {  
  36.                 e.printStackTrace(); 
  37.             }  
  38.         }  
  39.         return count;  
  40.     }  
  41.     @Benchmark  
  42.     public int outerForeach() {  
  43.         int count = 0;  
  44.         try {  
  45.             for (int i = 0; i < forSize; i++) {  
  46.                 if (i == forSize) {  
  47.                     throw new Exception("new Exception");  
  48.                 }  
  49.                 count++;  
  50.             }  
  51.         } catch (Exception e) {  
  52.             e.printStackTrace();  
  53.         }  
  54.         return count;  
  55.     }  

以上代碼的測試結(jié)果為:

從以上結(jié)果可以看出,程序在循環(huán) 1000 次的情況下,單次平均執(zhí)行時間為:

  •  循環(huán)內(nèi)包含 try-catch 的平均執(zhí)行時間是 635 納秒 ±75 納秒,也就是 635 納秒上下誤差是 75 納秒;
  •  循環(huán)外包含 try-catch 的平均執(zhí)行時間是 630 納秒,上下誤差 38 納秒。

也就是說,在沒有發(fā)生異常的情況下,除去誤差值,我們得到的結(jié)論是:try-catch 無論是在 for 循環(huán)內(nèi)還是  for 循環(huán)外,它們的性能相同,幾乎沒有任何差別。

try-catch的本質(zhì)

要理解 try-catch 的性能問題,必須從它的字節(jié)碼開始分析,只有這樣我能才能知道 try-catch 的本質(zhì)到底是什么,以及它是如何執(zhí)行的。

此時我們寫一個最簡單的 try-catch 代碼:

 
 
 
 
  1. public class AppTest {  
  2.     public static void main(String[] args) {  
  3.         try {  
  4.             int count = 0;  
  5.             throw new Exception("new Exception"); 
  6.         } catch (Exception e) {  
  7.             e.printStackTrace();  
  8.         }  
  9.     }  

然后使用 javac 生成字節(jié)碼之后,再使用 javap -c AppTest 的命令來查看字節(jié)碼文件:

 
 
 
 
  1.  javap -c AppTest   
  2. 警告: 二進制文件AppTest包含com.example.AppTest  
  3. Compiled from "AppTest.java"  
  4. public class com.example.AppTest {  
  5.   public com.example.AppTest();  
  6.     Code:  
  7.        0: aload_0  
  8.        1: invokespecial #1                  // Method java/lang/Object."":()V  
  9.        4: return  
  10.   public static void main(java.lang.String[]);  
  11.     Code:  
  12.        0: iconst_0  
  13.        1: istore_1  
  14.        2: new           #2                  // class java/lang/Exception  
  15.        5: dup  
  16.        6: ldc           #3                  // String new Exception  
  17.        8: invokespecial #4                  // Method java/lang/Exception."":(Ljava/lang/String;)V  
  18.       11: athrow  
  19.       12: astore_1  
  20.       13: aload_1  
  21.       14: invokevirtual #5                  // Method java/lang/Exception.printStackTrace:()V  
  22.       17: return  
  23.     Exception table:  
  24.        from    to  target type  
  25.            0    12    12   Class java/lang/Exception  

從以上字節(jié)碼中可以看到有一個異常表:

 
 
 
 
  1. Exception table:  
  2.        from    to  target type  
  3.           0    12    12   Class java/lang/Exception 

參數(shù)說明:

  •  from:表示 try-catch 的開始地址;
  •  to:表示 try-catch 的結(jié)束地址;
  •  target:表示異常的處理起始位;
  •  type:表示異常類名稱。

從字節(jié)碼指令可以看出,當(dāng)代碼運行時出錯時,會先判斷出錯數(shù)據(jù)是否在 from 到 to 的范圍內(nèi),如果是則從 target 標(biāo)志位往下執(zhí)行,如果沒有出錯,直接 goto 到 return。也就是說,如果代碼不出錯的話,性能幾乎是不受影響的,和正常的代碼的執(zhí)行邏輯是一樣的。

業(yè)務(wù)情況分析

雖然 try-catch 在循環(huán)體內(nèi)還是循環(huán)體外的性能是類似的,但是它們所代碼的業(yè)務(wù)含義卻完全不同,例如以下代碼:

 
 
 
 
  1. public class AppTest {  
  2.     public static void main(String[] args) {  
  3.         System.out.println("循環(huán)內(nèi)的執(zhí)行結(jié)果:" + innerForeach());  
  4.         System.out.println("循環(huán)外的執(zhí)行結(jié)果:" + outerForeach());  
  5.     }    
  6.     // 方法一  
  7.     public static int innerForeach() {  
  8.         int count = 0;  
  9.         for (int i = 0; i < 6; i++) {  
  10.             try {  
  11.                 if (i == 3) {  
  12.                     throw new Exception("new Exception");  
  13.                 } 
  14.                 count++;  
  15.             } catch (Exception e) {  
  16.                 e.printStackTrace(); 
  17.             } 
  18.         }  
  19.         return count;  
  20.     }  
  21.     // 方法二  
  22.     public static int outerForeach() {  
  23.         int count = 0;  
  24.         try {  
  25.             for (int i = 0; i < 6; i++) {  
  26.                 if (i == 3) {  
  27.                     throw new Exception("new Exception");  
  28.                 }  
  29.                 count++;  
  30.             }  
  31.         } catch (Exception e) {  
  32.             e.printStackTrace();  
  33.         }  
  34.         return count;  
  35.     }  

以上程序的執(zhí)行結(jié)果為:

 
 
 
 
  1. java.lang.Exception: new Exception 
  2.  
  3. at com.example.AppTest.innerForeach(AppTest.java:15) 
  4.  
  5. at com.example.AppTest.main(AppTest.java:5) 
  6.  
  7. java.lang.Exception: new Exception 
  8.  
  9. at com.example.AppTest.outerForeach(AppTest.java:31) 
  10.  
  11. at com.example.AppTest.main(AppTest.java:6) 
  12.  
  13. 循環(huán)內(nèi)的執(zhí)行結(jié)果:5 
  14.  
  15. 循環(huán)外的執(zhí)行結(jié)果:3 

可以看出在循環(huán)體內(nèi)的 try-catch 在發(fā)生異常之后,可以繼續(xù)執(zhí)行循環(huán);而循環(huán)外的 try-catch 在發(fā)生異常之后會終止循環(huán)。

因此我們在決定 try-catch 究竟是應(yīng)該放在循環(huán)內(nèi)還是循環(huán)外,不取決于性能(因為性能幾乎相同),而是應(yīng)該取決于具體的業(yè)務(wù)場景。

例如我們需要處理一批數(shù)據(jù),而無論這組數(shù)據(jù)中有哪一個數(shù)據(jù)有問題,都不能影響其他組的正常執(zhí)行,此時我們可以把 try-catch 放置在循環(huán)體內(nèi);而當(dāng)我們需要計算一組數(shù)據(jù)的合計值時,只要有一組數(shù)據(jù)有誤,我們就需要終止執(zhí)行,并拋出異常,此時我們需要將 try-catch 放置在循環(huán)體外來執(zhí)行。

總結(jié)

本文我們測試了 try-catch 放在循環(huán)體內(nèi)和循環(huán)體外的性能,發(fā)現(xiàn)二者在循環(huán)很多次的情況下性能幾乎是一致的。然后我們通過字節(jié)碼分析,發(fā)現(xiàn)只有當(dāng)發(fā)生異常時,才會對比異常表進行異常處理,而正常情況下則可以忽略 try-catch 的執(zhí)行。但在循環(huán)體內(nèi)還是循環(huán)體外使用 try-catch,對于程序的執(zhí)行結(jié)果來說是完全不同的,因此我們應(yīng)該從實際的業(yè)務(wù)出發(fā),來決定到 try-catch 應(yīng)該存放的位置,而非性能考慮。


文章標(biāo)題:啪啪打臉!領(lǐng)導(dǎo)說:try-catch要放在循環(huán)體外!
URL分享:http://www.5511xx.com/article/codciph.html