2012-03-29 44 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()但我扳指進入循環高於變量,除非它正在改變。