2012-03-29 15 views
0

JUnitを使用して並行性をテストするのは理想的ではありませんが、今のところ選択肢はありません。私は説明できない例外が発生しました。JUnitと並行処理:不可解なエラー

私は要約すると、テストを実行します。

  • 私はエグゼキュータ
  • 各実行可能に1000年ランナブルを提出するが、私はエグゼキュータ終了
  • JUnitのを待ちリスト
  • に要素を追加しますリストには999個の要素しかないことがわかります
  • runnable catchブロックには例外が出力されません

何が起こる可能性がありますか?

注:私は時々例外が発生します。コードには関連性のないものがいくつかありますが、私が何かを見逃してしまった場合に備えるために残しました。 XXXQueryはenumです。あなたはその周りに同期せずに、複数のスレッドでのごRunnable.run()方法でresultsArrayListに追加することはできません

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

+0

今後、Exceptionを提供し、どの行が有効になっているかを示してください。ありがとう。 – Gray

+0

@mcfinniganテストは1秒未満で完了します。 – assylias

答えて

2

アサーションに失敗したメッセージは、add()N_THREADSがコールされましたが、同時実行競合状態のためにエントリが少なくなっていることを示しています。

リストの代わりに最終的な配列を使用します。ような何か:また

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()を得ることはありませんが、それは変更されない限り、私は、ループ上の変数にそれを引っ張るだろう。