我正在做一个与数据库建立连接的项目。我需要查看exception is happening
有多少次。我正在使用Multithreaded code
,这意味着多个线程将连接到数据库并插入数据库。因此,在某些时候连接可能会丢失,因此我们需要查看这些异常发生了多少次。
所以我写了下面的代码,在catch块中,我捕捉到异常,并在每次出现异常时都对增加计数,并将其放入ConcurrentHashMap
中。
class Task implements Runnable {
public static final AtomicInteger counter_sql_exception = new AtomicInteger(0);
public static final AtomicInteger counter_exception = new AtomicInteger(0);
public static ConcurrentHashMap<String, Integer> exceptionMap = new ConcurrentHashMap<String, Integer>();
@Override
public void run() {
try {
//Make a db connection and then executing the SQL-
} catch (SQLException e) {
synchronized(this) {
exceptionMap.put(e.getCause().toString(), counter_sql_exception.incrementAndGet());
}
LOG.Error("Log Exception")
} catch (Exception e) {
synchronized(this) {
exceptionMap.put(e.getCause().toString(), counter_exception.incrementAndGet());
}
LOG.Error("Log Exception")
}
}
}
我的问题是-今天,我进行了一次代码审查,我的一位高级团队成员说,您将不需要
synchronized(this)
中exceptionMap
上的catch block
。我说是的,我们将需要这样做,因为增加计数器是原子的。在 map 中放置一个新值是原子的。但是,在没有同步的情况下进行这两者并不是原子的。他说ConurrentHashMap
将为您做到这一点。那么,是否需要在该
synchronized(this)
上添加exceptionMap
块?如果没有,那为什么呢?如果是,那我应该引用什么原因。 最佳答案
如果您要计算每个异常发生的次数,那么您需要这样的事情:
private static final ConcurrentMap<String, AtomicInteger> exceptionMap = new ConcurrentHashMap<String, AtomicInteger>();
private static void addException(String cause) {
AtomicInteger count = exceptionMap.get(cause);
if(count == null) {
count = new AtomicInteger();
AtomicInteger curCount = exception.putIfAbsent(cause, count);
if(curCount != null) {
count = curCount;
}
}
count.incrementAndGet();
}
请注意,除非定期清除,否则具有静态的异常映射是资源泄漏。
如@dnault所述,您还可以使用guava's AtomicLongMap。
更新:对您的原件的一些评论:
Task.class
)最后,如我的示例所示,