簡體   English   中英

計算catch塊中發生的異常數量

[英]Counting the number of exceptions happening in catch block

我試圖收集所有異常發生的計數和ConcurrentHashMap的異常名稱,以便我應該知道發生了多少次此異常。

因此,在我的catch塊中,我有一個映射,它將繼續添加異常名稱並且總計數發生。

下面是我的代碼which I have modified to always throw SQL Exception每次都為測試目的which I have modified to always throw SQL Exception ,以便我可以看到異常的計數是否准確。

所以某些情況 -

1)如果我選擇線程數為10 ,任務數為50 ,那么在該映射中,我可以看到該特定字符串的500個異常

2)但是如果我選擇的線程數為40 ,任務數為500那么我在該地圖19000不到20000異常,它顯示在19000左右。

我的問題是為什么? 我在這做什么錯?

class Task implements Runnable {

     public static final AtomicInteger counter_exception = new AtomicInteger(0);
     public static ConcurrentHashMap<String, Integer> exceptionMap = new ConcurrentHashMap<String, Integer>();

     @Override
     public void run() {

     try {

          //Making a db connection and then executing the SQL-

         } catch (SQLException e) {
               exceptionMap.put(e.getCause().toString(), counter_exception.incrementAndGet());
          } catch (Exception e) {

          }
     }

    }

更新:

如果我有這樣的東西 - 我得到40個線程和4000 taks的Null Pointer Exception 為什么?

catch (SQLException e) {

synchronized(this) {
                   exceptionMap.put(e.getCause().toString(), counter_exception.incrementAndGet());
}              
}

也許這樣的事情正在發生:

任務1-500:捕獲異常,准備調用exceptionMap.put ,從counter_exception.incrementAndGet()獲取一個傳遞給所述方法的數字

任務500:原子整數計數器中的數字500已被調度,因此其exceptionMap.put首先運行

任務1:原子整數計數器中的數字1已被調度,因此其exceptionMap.put最后運行

現在即使計數器是500並且我們有500個例外,異常消息也會與1相關聯,因為它是最近執行的。

這讓我覺得這是錯誤的做法。

如果您在加載的應用程序中遇到異常,您應該找到這些異常的原因(或原因)並修復它們。

計算異常並沒有幫助。 事實上,您可能會通過以下方式使問題變得更糟:

  • 使您的代碼難以理解您要添加的額外復雜性,
  • 導致症狀改變,使得識別導致它們的錯誤變得更加困難,並且
  • 由於您計算異常的方式錯誤而引入新錯誤。

好的,那么你能做些什么來讓問題更容易找到?

  • 檢查您的代碼庫以確保您不會擠壓異常。
  • 查找未記錄異常的異常處理程序。
  • 尋找過於廣泛的異常處理程序; 例如,對於ExceptionRuntimeExceptionThrowable
  • 尋找過早捕獲異常的異常處理程序。 如果您有意外的異常,您可以做的最好的事情是允許它傳播到“頂部”並終止應用程序或(對於Web容器)當前請求。 嘗試進行更具體的恢復是一個壞主意......“因為您的代碼不知道異常的含義或導致它的原因。
  • 最后,確保所有線程都有一個未捕獲的異常處理程序...以便至少記錄任何未捕獲的異常。

如果在應用程序處於負載狀態時出現異常(特別是奇怪的異常),則可能存在由兩個或多個線程共享且未正確同步的數據結構/對象/變量。 我建議您對代碼庫進行代碼審查,以查找此類問題。


UPDATE

查看更新的代碼,NPE最可能的原因是e.getCause()返回null ; 即你的一些例外沒有鏈式“原因”異常! 處理這應該是微不足道的; 即測試e.getCause()返回的值。

請注意,由於您使用的是ConcurrentHashMap ,因此不能將null用作鍵。 這是明確禁止的 - 請參閱javadoc。

另一個可能的原因是錯誤同步。

synchronized(this) {
    exceptionMap.put(e.getCause().toString(), 
                     counter_exception.incrementAndGet());
}

問題是,你正在同步上this ,並執行相同的代碼其他線程都會有不同的this ......這樣你就不會跟他們同步。

但是,我很確定你實際上不需要與其他線程同步,因為:

  • 靜態變量在類初始化期間初始化,並且(可能)之后沒有分配,並且
  • 您在共享對象上進行的方法調用是線程安全的。

我會將exceptionMap聲明為final ,並刪除synchronized塊。

如果確實需要同步,則應該同步這兩個靜態對象之一,或者可能在Task.classTask.class

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM