1

マルチスレッドコードで発生countする数を調べています。exceptionsそのために私がしたことはaddExceptionAtomicInteger.

addExceptionメソッドは 2 つのパラメーターを受け入れます。one is the Stringその他は、boolean flag例外のためにプログラムを終了するかどうかを意味します。つまり、そのフラグが true の場合、例外が発生するたびにプログラムを終了する必要があります。

したがって、下の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 に答える