在 Java 中对多线程代码做单元测试是一个常见但容易踩坑的问题。下面从思路、常见工具、示例、注意事项几个层面系统讲一下。
多线程单元测试的目标不是“测线程本身”,而是:
验证并发逻辑的正确性、可见性、原子性、同步是否正确
常见测试点:
synchronized / Lock 是否正确wait/notify、CountDownLatch)CountDownLatch 控制线程执行这是最通用、最稳定的方式。
public class Counter {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
❌ 非线程安全,测试应能发现问题:
@Test
public void testCounter() throws InterruptedException {
Counter counter = new Counter();
int threadCount = 10;
int perThread = 1000;
CountDownLatch start = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
try {
start.await();
for (int j = 0; j < perThread; j++) {
counter.increment();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
end.countDown();
}
}).start();
}
start.countDown();
end.await();
System.out.println(counter.getCount());
}
✅ 用于:
ExecutorService + Future适合测试线程池逻辑:
ExecutorService pool = Executors.newFixedThreadPool(4);
List<Future<Integer>> futures = new ArrayList<>();
for (int i = 0; i < 4; i++) {
futures.add(pool.submit(() -> 1));
}
int sum = 0;
for (Future<Integer> f : futures) {
sum += f.get();
}
pool.shutdown();
jcstress(JVM 并发压力测试)官方并发测试工具,用于:
@JCStressTest
@Outcome(id = "1", expect = Expect.ACCEPTABLE)
@State
public class VolatileTest {
int x;
volatile int y;
@Actor
public void actor1() {
x = 1;
y = 1;
}
@Actor
public void actor2(II_Result r) {
r.r1 = y;
r.r2 = x;
}
}
✅ 用于底层并发模型验证
TestableMock / Mockito + 线程Mock 不改变并发本质,只用于:
when(service.getData()).thenReturn("mock");
ConcurrentUnit(轻量级)@Test
public void testConcurrency() {
ConcurrentTestCase tc = new ConcurrentTestCase();
tc.runThreads(10, () -> {
// 并发逻辑
});
}
thread.run(); // 错误
✅ 必须用 start()
Thread.sleep() 断言✅ 用 CountDownLatch / CyclicBarrier
并发 bug 是概率性的
| 场景 | 推荐方式 |
|---|---|
| 业务并发逻辑 | CountDownLatch + JUnit |
| 线程池 | ExecutorService |
| 底层并发模型 | jcstress |
| 死锁检测 | ThreadMXBean |
| 可见性 / volatile | jcstress |
多线程单元测试的本质:用同步工具控制线程执行顺序,验证并发结果是否稳定正确。
如果你有:
可以直接贴代码,我可以帮你写可直接跑的测试。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。