传说中“Go 天生为高并发而生”,Java 21 虚拟线程又说“革命性突破”——
那到底谁更能抗压?
我拿自己的电脑,真测了一次。
一、测试环境
| 项目 | 参数 |
|---|---|
| 设备 | MacBook Pro M1 Max(10核CPU / 32GB内存) |
| 系统 | macOS 15.6 |
| Go 版本 | Go 1.25 |
| Java 版本 | JDK 21(启用虚拟线程) |
| 压测工具 | wrk |
| 命令 | wrk -t8 -c2000 -d30s http://127.0.0.1:8080/cpu |
说明:同一机器、同一接口逻辑、同一压测参数。 公平、公正、实测无P。
二、测试接口逻辑
两种语言都实现同样的 /cpu 接口, 执行一段质数计算,然后返回ok。
Go 代码:
func handler(w http.ResponseWriter, r *http.Request) {
for i := 2; i < 50000; i++ { isPrime(i) }
fmt.Fprint(w, "ok")
}
Java 代码:
server.createContext("/cpu", exchange -> {
for (int i = 2; i < 50000; i++) isPrime(i);
exchange.sendResponseHeaders(200, 2);
exchange.getResponseBody().write("ok".getBytes());
exchange.close();
});
三、实测结果
| 指标 | Go 1.25 | Java 21 虚拟线程 |
|---|---|---|
| 吞吐量(RPS) | 8040 | 923 |
| 平均延迟 | 30.37 ms | 165.77 ms |
| 最大延迟 | 749 ms | 1.98 s |
| 错误率 | 0.7% | 10%+ |
| CPU/内存 | 高效 / 1.5GB | 吃紧 / 3GB+ |
Go 的吞吐是 Java 的约 8.7 倍,延迟仅为其 1/5。
四、核心结论
-
Go 天生并发友好 goroutine 调度在用户态完成,创建快、切换轻,每个只占几 KB 内存,百万并发轻松跑。
-
Java 虚拟线程进步巨大但仍偏重 虽然比传统线程好很多,但受 JVM、GC 和 IO 栈影响,极限压力下仍有明显抖动。
-
同机实测,差距实打实 Go 平稳输出 8K QPS,Java 在 1K 附近开始吃力。
五、为什么差这么多?
一句话概括: Go 用用户态调度百万轻量协程; Java 还是要和 JVM、GC、内核线程打交道。
前者像灵巧的群蜂在并行采蜜, 后者像穿着盔甲冲锋的骑士——稳定但笨重。
六、如果你要选语言
| 场景 | 推荐 |
|---|---|
| 网关、推送、爬虫、采集、边缘服务 | Go |
| 企业级系统、业务复杂度高 | Java |
| 想在一台机器上跑出最大并发 | Go 毫无悬念 |
七、结尾总结
同样的电脑、同样的接口、同样的压测:
Go 每秒 8040 请求 Java 每秒 923 请求
高并发之战, Go 依然是那把最锋利的刀。