我正在尝试收集ConcurrentHashMap
中发生异常的所有计数和异常名称,以便我知道此异常发生了多少次。
所以在我的catch块中,我有一个地图,它将继续添加异常名称并且总计数发生。
以下是我的代码which I have modified to always throw SQL Exception
每次用于测试目的,以便我可以看到异常的计数是否准确。
某种情况 -
1)如果我选择线程数为10
,任务数量为50
,那么在该地图中,我可以看到该特定字符串的500个异常
2)但是,如果我选择的线程数为40
,任务数量为500
,那么我在该地图中看不到20000
个例外,它显示{{1} }}。
我的问题是为什么?我在这做错了什么?
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
答案 0 :(得分:2)
也许这样的事情正在发生:
任务1-500:抓住例外,准备拨打exceptionMap.put
,从counter_exception.incrementAndGet()
获取传递给所述方法的号码
任务500:原子整数计数器中的数字500已被调度,因此其exceptionMap.put
先运行
任务1:原子整数计数器中的数字1已被调度,因此其exceptionMap.put
最后运行
现在即使计数器是500并且我们有500个例外,异常消息也会与1相关联,因为它是最近执行的。
答案 1 :(得分:1)
这让我觉得这是错误的做法。
如果您在加载的应用程序中遇到异常,您应该找到这些异常的原因(或原因)......并修复它们。
计算例外情况无济于事。事实上,你可能会通过以下方式使问题变得更糟:
好的,那么你能做些什么才能让问题更容易找到?
Exception
或RuntimeException
或Throwable
。如果在应用程序处于负载状态时出现异常(特别是奇怪的异常),则可能存在由两个或多个线程共享且未正确同步的数据结构/对象/变量。我建议您对代码库进行代码审查查找以解决此类问题。
<强>更新强>
查看更新的代码,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.class
。