我有一个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()没有改变。
任何人都可以为我解释一下吗?
答案 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中的每个代码字符串值都应该是唯一的。您还可以减少迭代次数以获得更好的调试...