【问题标题】:Java multi-thread does not update value in unit testJava多线程在单元测试中不更新值
【发布时间】:2017-04-14 08:36:05
【问题描述】:

我有一个 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());

}
}

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

另一方面,如果我尝试在线程中更新 service 实例的值,我也会发现这些值没有保存。例如

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

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

谁能帮我解释一下?

【问题讨论】:

    标签: java spring multithreading unit-testing


    【解决方案1】:

    这段代码有很多错误。

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

    2) 在进行断言之前,您无需等待提交的线程完成。要么使用invokeAll 启动多个线程,要么通过在执行器上执行shutdown 然后awaitTermination 等待所有线程完成。如需更好的解释,请参阅此问题:ExecutorService, how to wait for all tasks to finish

    【讨论】:

    • 感谢 @john16384,我将 Set 更改为 ConcurrentHashMap,并添加了 executor.awaitTermination(5, TimeUnit.SECONDS)。这样可以吗?
    • 这样做的机会要高得多。对其进行更多测试,看看它现在是否按预期工作。不要忘记在awaitTermination 之前也调用shutdown
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多