1

ConcurrentHashMapこの例外が何回発生したかを認識できるように、発生した例外の数と例外の名前をすべて収集しようとしています。

したがって、キャッチブロックには、例外の名前を追加し続けるマップがあり、そこに合計カウントが発生します。

以下は、which I have modified to always throw SQL Exception例外の数が正確かどうかを確認できるように、テスト目的で毎回私のコードです。

だから特定のシナリオ-

1) スレッド10数を として、タスク数をとして選択50している場合、そのマップでは、その特定の文字列に対して 500 の例外が表示されます。

2)しかし、スレッド40数とタスク数を選択している場合、そのマップに例外が表示され500ず、周りに表示されます。2000019000

私の質問はなぜですか?私はここで何をしているのですか?

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) {

          }
     }

    }

更新しました:

このようなものがある場合Null Pointer Exception、40 スレッドと 4000 タスクを取得しています。なんで?

catch (SQLException e) {

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

2 に答える 2

2

たぶん、このようなことが起こっています:

タスク1-500:例外をキャッチし、呼び出す準備をしexceptionMap.put、そこから番号を取得counter_exception.incrementAndGet()して、上記のメソッドに渡します

タスク500:アトミック整数カウンターから500番があり、exceptionMap.put最初に実行されるようにスケジュールされています

タスク1:アトミック整数カウンターから1番があり、exceptionMap.put最後に実行されるようにスケジュールされています

これで、カウンターが500で、500の例外が発生した場合でも、最後に実行されたため、例外メッセージは1に関連付けられます。

于 2013-02-08T23:59:18.577 に答える
1

これは間違ったアプローチだと思います。

負荷がかかっているアプリケーションで例外が発生している場合は、それらの例外の原因を見つけて修正する必要があります。

例外を数えても役に立ちません。実際、次のことによって問題を悪化させる可能性があります。

  • 追加している余分な複雑さに対してコードを理解するのが難しくなります。
  • 症状の変化を引き起こし、症状の原因となっているバグを特定するのが難しくなります。
  • 例外をカウントする方法の間違いによる新しいバグの導入。

では、問題を見つけやすくするにはどうすればよいでしょうか?

  • コードベースを見直して、例外 をつぶしていないことを確認してください。
  • 例外をログに記録しない例外ハンドラーを探します。
  • 過度に広範な例外ハンドラを探します。たとえば、ExceptionまたはRuntimeExceptionまたはThrowable
  • 例外をキャッチするのが早すぎる例外ハンドラーを探します。予期しない例外が発生した場合、できる最善の方法は、それを「最上位に」伝播させ、アプリケーションまたは (Web コンテナーの場合) 現在の要求を強制終了することです。より具体的な回復を試みるのは悪い考えです...「あなたのコードは例外の意味や原因を知らないからです.
  • 最後に、すべてのスレッドにキャッチされていない例外ハンドラーがあることを確認してください...キャッチされていない例外が少なくともログに記録されるようにします。

アプリケーションに負荷がかかっているときに例外が発生する場合 (特に異常な場合)、データ構造 / オブジェクト / 変数が 2 つ以上のスレッドで共有され、適切に同期されていない可能性があります。この種の問題を探して、コードベースのコード レビューを行うことをお勧めします。


アップデート

更新されたコードを見ると、NPE の最も可能性の高い原因は、それe.getCause()が返されていることですnull。つまり、いくつかの例外には連鎖した「原因」例外がありません! それは対処するのが簡単なはずです。つまり、 によって返される値をテストしますe.getCause()

を使用しているため、キーとしてConcurrentHashMap使用できないことに注意してください。nullこれは明示的に禁止されています - javadoc を参照してください。

別の考えられる原因は、同期が正しくないことです。

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

問題は、 で同期していてthis、同じコードを実行している他のスレッドのコードが異なるthisことです ... そのため、それらと同期しません。

ただし、次の理由により、実際に他のスレッドと同期する必要はないと確信しています。

  • 静的変数はクラスの初期化中に初期化され、(おそらく) その後は割り当てられません。
  • 共有オブジェクトに対して行っているメソッド呼び出しはスレッドセーフです。

であると宣言exceptionMapfinal、ブロックを取り除きsynchronizedます。

本当に同期する必要がある場合は、これら 2 つの静的オブジェクトのいずれか、またはおそらく で同期する必要がありますTask.class

于 2013-02-09T02:33:59.980 に答える