1

我正在考虑多线程代码中发生count的次数。exceptions因此,我所做的是,我创建了一种方法addException,在该方法中我使用AtomicInteger.

addException方法接受两个参数,one is the String和 otherboolean flag表示我们是否要因为任何异常而终止程序。意思是,如果该标志为真,那么只要有任何异常,我都需要终止程序。

因此,如果您查看我的下面的catch块,我有addException用于计算异常的方法调用,并且在该方法调用下面我也在记录异常。

ExecutorService service = Executors.newFixedThreadPool(threads);

    for (int i = 0; i < threads; i++) {
            service.submit(new ReadTask());
    }

class ReadTask implements Runnable {

    public static ConcurrentHashMap<String, AtomicInteger> exceptionMap = new ConcurrentHashMap<String, AtomicInteger>();

public ReadTask() {

}

@Override
public run() {

    try {

        .........

    } catch (ClassNotFoundException e) {
        addException(e.getCause() != null ? e.getCause().toString() : e.toString(), Read.flagTerminate);
        LOG.error("Threw a ClassNotFoundException in " + getClass().getSimpleName(), e);
    } catch (SQLException e) {
        addException(e.getCause() != null ? e.getCause().toString() : e.toString(), Read.flagTerminate);
        LOG.error("Threw a SQLException while making connection to database in " + getClass().getSimpleName(), e);
    }
}

    /**
     * A simple method that will add the count of exceptions and name of
     * exception to a map
     * 
     * @param cause
     * @param flagTerminate 
     */
    private static void addException(String cause, boolean flagTerminate) {
        AtomicInteger count = exceptionMap.get(cause);
        if (count == null) {
            count = new AtomicInteger();
            AtomicInteger curCount = exceptionMap.putIfAbsent(cause, count);
            if (curCount != null) {
                count = curCount;
            }
        }
        count.incrementAndGet();

        if(flagTerminate) {
            System.exit(1);
        }
    }
}

问题陈述:-

此代码是否可能存在任何线程争用?如果是,我怎样才能addException以更好的方式编写方法来避免Thread Contention

这里有没有更有效的写法addException

4

2 回答 2

2

您的代码在逻辑上看起来是正确的,但仍然存在线程争用的可能性。

考虑如果每个线程都抛出相同的异常会发生什么:它们将在更新AtomicInteger跟踪异常计数时进行序列化。

解决这个问题真的没有简单的方法:如果所有线程都在更新同一条数据,那么它们几乎必须序列化。这不是问题。那只是现实。

很多方法可以解决这个问题,但它会将一段简单、正确的代码变成一场复杂的噩梦。

您应该问的问题是“我需要提高效率吗?” 答案很可能是否定的,因为几乎按照定义,例外情况很少见。只有在前一个问题的答案是肯定的情况下,才应该问“我如何使它更有效率”的问题。

于 2013-03-01T05:13:58.017 回答
0
   //This check-then-act block can cause two threads can see count as null
    if (count == null) {
        count = new AtomicInteger();
        AtomicInteger curCount = exceptionMap.putIfAbsent(cause, count);
        if (curCount != null) {
            count = curCount;
        }
    }

Map<Class<?>,AtomicInteger>建议:1) where Class 将是异常的类怎么样。

更新: 尝试ThreadLocals在这里使用每个线程将拥有自己的地图副本,并将在自己的副本中更新。所以零争用。

于 2013-03-01T04:57:42.187 回答