终极指南:如何在PC上免费体验Switch游戏?Ryujinx模拟器完整配置教程
2026/4/20 21:38:16
最近再做文件流传输,发现JDK更新新的东西,而网上都还没有具体的应用方法。
现在 JDK 21 已 GA,虚拟线程官宣“同步代码跑出异步性能”,于是有了这篇“2025 版全家桶”。
不管你是刚学 Java 的本科生,还是天天调网关的社畜,都能 10 分钟看完、5 分钟定位线上慢 IO。
BIO(同步阻塞) → NIO(同步非阻塞) → AIO(异步回调) → 虚拟线程(阻塞代码+纤程)把鼠标滚轮锁死,下面按顺序展开。
finally close()。InputStream.transferTo(OutputStream)是 JDK 9 送的零拷贝语法糖,8 行代码缩成 1 行。StandardCharsets.UTF_8,别再catch UnsupportedEncodingException骗自己。BufferedInputStream再套GZIPInputStream,顺序反了性能掉 30%。DirectBuffer vs HeapBuffer
-XX:MaxDirectMemorySize,别等 OOM 再百度。零拷贝“两板斧”
fileChannel.transferTo()—— 内核 sendfile,用户态 0 拷贝。FileChannel.map()—— 大文件随机读写像操作数组,单机 10 Gbps 打满 CPU 还能剩 70%。Reactor 模型手绘版
MainReactor→只 accept ↓ SubReactor→真正 read/writeNetty 默认就是这个套路,8 核 16 G 云主机轻松 100 w 并发。
AsynchronousSocketChannel+CompletionHandler确实能把线程数压到几十,
代价是“回调地狱”+“调试断点找不到北”。
除非写代理网关、计算量极轻,否则 Reactor 更简单。
代码还是最古老的阻塞写法:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { executor.submit(() -> { var in = socket.getInputStream(); // 阻塞读 }); }底层把 1 w 个虚拟线程挂到 1 个平台线程上,阻塞操作不再占内核栈。
官方 benchmark:Tomcat NIO 7 w QPS → Virtual Thread 12 w QPS,延迟还降一半。
结论:新项目直接上 JDK21,写完同步代码就可以去喝茶。
strace -c -e trace=%network java Appread/write系统调用次数,比业务预期高 1 个量级 → 没加 Buffer。perf stat -e cache-missesjstack | grep 'parking to wait'park→ 连接数 > 线程池,上 Selector 或虚拟线程。BufferedOutputStream忘记flush(),文件 0 字节。Selector.selectedKeys()用完必须remove(),否则死循环。FileChannel.map一次 map 2 GB,32 位 JVM 直接 OOM。synchronized会钉死平台线程,改ReentrantLock。| 场景 | 推荐方案 | 一句话理由 |
|---|---|---|
| < 100 MB 文件顺序读写 | Files.newInputStream + try-with-resources | 简单够用 |
| 高并发网关(>1 w 连接) | Netty 主从 Reactor | 业界验证,文档管够 |
| 超大文件拷贝(>2 GB) | fileChannel.transferTo | 内核零拷贝,CPU 省一半 |
| 纯代理/转发,CPU 几乎不计算 | AIO | 线程数压到最低 |
| JDK21 新项目 | Virtual Thread + 阻塞 IO | 代码最懒,性能最猛 |
把这篇文章保存为「IDEA 收藏夹」第一条,下次: