JUnit和并发:莫名其妙的错误

时间:2012-03-29 16:28:39

标签: java multithreading concurrency junit

我在一些帖子中读到使用JUnit测试并发性并不理想,但我现在别无选择。我刚遇到一个我无法解释的异常。

我在一个测试中进行了总结:

  • 我向执行人提交了1000个runnables
  • 每个runnable都会向列表中添加一个元素
  • 我等待执行人终止
  • JUnit告诉我列表中只有999个元素
  • 在runnable catch块中没有打印异常

什么可能导致这种行为?

注意:我不时会得到例外。代码有一些不相关的东西,但我把它留在那里以防我错过了什么。 XXXQuery是一个枚举。

public void testConcurrent() throws InterruptedException {
    final int N_THREADS = 1000;
    final XXXData xxxData = new AbstractXXXDataImpl();
    final List<QueryResult> results = new ArrayList<>();
    ExecutorService executor = Executors.newFixedThreadPool(N_THREADS);
    for (int i = 0; i < N_THREADS; i++) {
        final int j = i;
        executor.submit(new Runnable() {

            @Override
            public void run() {
                try {
                    results.add(xxxData.get(XXXQuery.values()[j % XXXQuery.values().length]));
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        });
    }
    executor.shutdown();
    executor.awaitTermination(10, TimeUnit.SECONDS);
    assertEquals(N_THREADS, results.size());
}

1 个答案:

答案 0 :(得分:2)

您无法在多个线程中的results方法中添加ArrayList Runnable.run(),而无需在其周围进行同步。

断言失败消息显示尽管对N_THREADS进行了add()次调用,但由于并发争用条件,ArrayList得到的条目较少。

我会使用最终数组而不是列表。类似的东西:

final QueryResult[] results = new QueryResult[N_THREADS];
for (int i = 0; i < N_THREADS; i++) {
    ...
        public void run() {
            results[j] = data.get(Query.values()[j % Query.values().length]);
        }

另外,我不太了解XXXQuery.values()但是我会把它拉到循环上面的变量中,除非它正在改变。