Java多线程不会在单元测试中更新值

时间:2017-04-14 08:36:06

标签: java spring multithreading unit-testing

我有一个Spring服务,我想测试它对并发线程的正确性。

@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());

}
}

我想断言生成了多少代码并检查是否有重复的代码。 但结果设置为空。我不知道为什么。

另一方面,如果我尝试更新线程中服务实例的值,我也发现不保存这些值。 e.g。

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

最后,service.getValue()没有改变。

任何人都可以为我解释一下吗?

2 个答案:

答案 0 :(得分:3)

这段代码有很多错误。

1)您正在使用HashSet并在多个线程中更新它,但HashSet被记录为不是线程安全的。这会导致意外行为,或者如果你幸运的话ConcurrentModificationException。将其包装在同步集中。

2)在进行断言之前,您没有等待提交的线程完成。使用invokeAll启动多个线程,或者在执行程序上执行shutdown,然后awaitTermination等待所有线程完成。有关更好的说明,请参阅此问题:ExecutorService, how to wait for all tasks to finish

答案 1 :(得分:3)

是否有"code"输出字符串与已添加到hashset的字符串冲突的情况?在这种情况下,代码字符串刚刚覆盖在hashset上。所以,我想说的是,hashset中的每个代码字符串值都应该是唯一的。您还可以减少迭代次数以获得更好的调试...