2012-03-29 58 views
0

我在几篇文章中读到,使用JUnit测试并发性并不理想,但现在我没有选择。我刚刚遇到了一个我无法解释的例外。JUnit和并发:莫名其妙的错误

我运行一个测试,其中,在总结:

  • 我提交1000个可运行于执行
  • 每个可运行将元素添加到列表
  • 我等待执行终止
  • 的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()); 
} 
+0

也许在某些情况下10秒是不够长的所有1000线程完成? – mcfinnigan 2012-03-29 16:34:04

+0

将来,请提供例外情况并显示哪一行生效。谢谢。 – Gray 2012-03-29 16:35:05

+0

@mcfinnigan测试完成时间不到一秒钟。 – assylias 2012-03-29 16:35:11

回答

2

在多线程的Runnable.run()方法的周围没有同步您不能添加到resultsArrayList

断言失败消息显示虽然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()但我扳指进入循环高于变量,除非它正在改变。

相关问题