2017-04-14 73 views
1

我有一個Spring服務,我想測試它的併發線程的正確性。Java多線程不會在單元測試中更新值

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringBootTest 
public class SerialNumberServiceTest { 

@Autowired 
private SerialNumberService service; 

private final static int NUM_THREADS = 10; 
private final static int NUM_ITERATIONS = 100; 

@Test 
public void testSynchronized(){ 
    ExecutorService executor = Executors.newFixedThreadPool(10); 
    final Set<String> result = new HashSet<String>(); 
    int size = 0; 

    for(int i = 0; i < NUM_THREADS; i++){ 
     executor.submit(new Runnable() { 
      @Override 
      public void run() { 
       for (int j = 0; j < NUM_ITERATIONS; j++) { 
        String code = service.generateSerialNumberByModelCode("LP"); 
        result.add(code); 
       } 
      } 
     }); 
    } 

    assertEquals(NUM_ITERATIONS * NUM_THREADS, result.size()); 

} 
} 

我想聲明生成了多少代碼並檢查是否有重複代碼。 但結果設置爲空。我不知道爲什麼。另一方面,如果我嘗試在線程中更新服務實例的值,我也會發現這些值不會保存。例如

public void run() { 
      for (int j = 0; j < NUM_ITERATIONS; j++) { 
       String code = service.generateSerialNumberByModelCode("LP"); 
       service.incrValue(); 
       result.add(code); 
      } 
    } 

最後,service.getValue()是不變的。

任何人都可以爲我解釋這個嗎?

回答

3

這段代碼有很多錯誤。

1)您正在使用HashSet並在多個線程中更新它,但HashSet被記錄爲不是線程安全的。這會導致意想不到的行爲,或者如果你幸運的話,ConcurrentModificationException。將其包裝在同步設置中。

2)您不會在等待提交的線程完成之前完成斷言。使用invokeAll來啓動多個線程,或通過在執行程序上執行shutdown然後awaitTermination等待所有線程完成。爲更好的解釋,請參閱此問題:ExecutorService, how to wait for all tasks to finish

+0

感謝@ john16384,我將Set更改爲ConcurrentHashMap,並添加了executor.awaitTermination(5,TimeUnit.SECONDS)。這個可以嗎? – BurnetZhong

+0

你有很高的機會做你期望的事情。再測試一下,看看它現在是否按預期工作。不要忘記在'awaitTermination'之前調用'shutdown'。 – john16384

2

是否有任何情況下"code"輸出字符串與已添加到哈希集的字符串衝突?在這種情況下,在hashset上剛剛覆蓋的代碼字符串。所以,我想說,也許哈希集中的每個代碼字符串值都應該是唯一的。您也可以減少迭代次數以更好地調試...