junit 5 默认串行执行,需通过 junit-platform.properties 或 maven surefire 插件启用并行(如设置 junit.jupiter.execution.parallel.enabled=true),并配合 @execution(concurrent) 注解及 @resourcelock 控制资源同步,方可实现真正并发。

JUnit 5 原生支持并行执行测试,但默认是**串行**的。要真正利用多核 CPU 提升测试执行效率,需显式启用并行模式,并合理配置执行策略和资源同步机制。
启用并行执行的核心配置
仅加注解不够,必须配合 junit-platform.properties 或 Maven Surefire 插件配置,否则 @Execution(ExecutionMode.CONCURRENT) 不生效。
- 在
src/test/resources/junit-platform.properties中添加:
jest.jupiter.execution.parallel.enabled=true junit.jupiter.execution.parallel.config.dynamic.factor=2 junit.jupiter.execution.parallel.mode.default=concurrent junit.jupiter.execution.parallel.mode.classes.default=concurrent
- 或在 Maven 的
pom.xml中配置 Surefire 插件(推荐):
<plugin><groupid>org.apache.maven.plugins</groupid><artifactid>maven-surefire-plugin</artifactid><version>3.0.0-M5</version><configuration><properties><configurationparameters>
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
</configurationparameters></properties></configuration></plugin>
按类或方法粒度控制并发行为
JUnit 5 提供两级并行控制:测试类级别和测试方法级别。两者可组合使用,但需注意作用范围。
- 在测试类上标注,表示该类内所有
@Test方法可并发执行:
@Execution(ExecutionMode.CONCURRENT)
class ConcurrentTestClass { ... }
- 在单个测试方法上标注,仅对该方法生效(类级未启用时也有效):
@Test
@Execution(ExecutionMode.CONCURRENT)
void testWithSharedResource() { ... }
- 若类已标注
@Execution(CONCURRENT),但某个方法需串行(如操作静态变量),可用:
@Test
@Execution(ExecutionMode.SAME_THREAD)
void mustRunAlone() { ... }
避免并发冲突:用 @ResourceLock 保护共享资源
并行执行时,多个测试可能同时读写同一资源(如 System.setProperty、静态字段、临时文件等),导致断言不稳定。JUnit 5 提供声明式锁机制。
-
@ResourceLock("system.props")表示该测试需独占访问名为"system.props"的资源; - 搭配
ResourceAccessMode.READ_WRITE(默认)用于写操作,READ用于只读场景,允许多个读操作并发; - 可跨类生效——只要锁名一致,不同测试类中的方法也会排队执行。
示例:
@Test
@ResourceLock("system.props")
void setsCustomProperty() {
System.setProperty("test.key", "value");
}
@Test
@ResourceLock(value = "system.props", mode = ResourceAccessMode.READ)
void readsCustomProperty() {
assertNotNull(System.getProperty("test.key")); // 安全读取
}
验证并行是否生效
光看执行时间不够,建议加日志或计数器确认线程实际并发:
- 在测试方法中打印当前线程名:
System.out.println(Thread.currentThread().getName()); - 观察输出中是否出现多个
ForkJoinPool-worker-N线程交替执行; - 用 JVisualVM 或
jstack查看测试进程的活跃线程数是否接近 CPU 核心数; - 注意:Maven 默认 fork 一个 JVM 进程运行测试,确保 Surefire 的
forkCount不设为 1(会禁用并行)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











