验证ArrayList并发修改异常:多线程触发registry方法的单元测试是否正确?
单元测试实现问题分析
你的这个单元测试实现存在多处错误,完全无法达到验证并发修改异常的目标,核心问题如下:
- 变量名不匹配:你定义的异常触发标记是
AtomicBoolean terminate,但捕获ConcurrentModificationException时调用的是endExecution.set(true),两个变量完全无关,哪怕真的抛出了目标异常,也不会修改terminate的值,后续的断言永远都会通过,根本检测不到异常。 - 测试前提不成立:你要测试的
registry()方法已经加了synchronized修饰,只要该方法内部对customerData这个ArrayList的所有操作都没有外部并发读写的情况,多线程调用该方法时会串行执行,本来就不会触发并发修改异常,测试逻辑和你的目标场景完全不匹配。 CountDownLatch逻辑错误:你初始化latch的计数是100,但每个线程的while循环中每执行一次registry()就会调用一次latch.countDown(),只要10个工作线程累计跑满100次就会触发latch.await()返回,主线程直接往下执行,测试运行时长完全不可控,很可能还没触发并发场景就已经跑完了。- 断言逻辑完全写反:你的测试目标是验证存在并发修改异常,预期结果应该是异常触发后标记位为
true,但你写的assertEquals(terminate.get, false)是验证没有抛出异常,完全不符合测试目标。 - 资源未释放:测试结束后没有调用
ExecutorService.shutdown()关闭线程池,会产生线程驻留的问题。
优化建议
如果要复现ArrayList的并发修改异常,你可以按以下逻辑调整:
- 先确认
registry()方法的synchronized修饰是否要保留,如果是要测加锁前的并发问题,先去掉该修饰符,或者构造其他线程同时读写customerData的场景。 - 统一异常标记变量名,捕获到目标异常后正确修改标记位。
- 调整并发逻辑:可以固定每个线程执行N次
registry()调用,累计总调用量上万次提升触发并发问题的概率,也可以给单测加超时时间避免无限卡死。 - 修正断言逻辑:确认预期结果是触发异常后标记位为
true。 - 测试结束后主动关闭线程池。
内容的提问来源于stack exchange,提问作者explorer
相关产品推荐
相关产品推荐

