一、同步并发编程困境-线程爆炸
为了提高系统利用率,进程发展到多线程,但是多线程并不完美
- 问题 1:线程等待或线程阻塞。CPU浪费。线程池满而拒绝服务。
- 问题 2:创建更多线程可能会导致 JVM 崩溃(内存不足)。每个线程大概需要占用1M内存。
一) 典型线程池应用
二、技术的发展和探索
一)提高线程利用率:阻塞IO和非阻塞IO
- 阻塞IO:
- 非阻塞IO:
- servlet3.1和tomcat对非阻塞IO的支持:
二)减少线程使用(不阻塞线程):事件驱动, Reactive, Future
- 事件驱动:
- Reactive响应式编程:
- Spring Future异步方法编排:
三)非阻塞NIO和事件驱动结合:Netty和HSF异步,HttpAsyncClient, 异步Tair
- Netty:
- SpringFlux:
- Apache的HttpAsyncClient
- Tair异步SDK
四)轻量级线程:纤程(Fiber),协程(coroutine),虚拟线程(VirtualThread)
异步响应式的问题:1. 需要学习一种新的编程模式,学习曲线略高。 2. 调用追踪困难。3. 只要有一个库不支持响应式就会导致响应式失效。
void handle(Request request, Response response) {
var url1 = ...
var url2 = ...
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
var future1 = executor.submit(() -> fetchURL(url1));
var future2 = executor.submit(() -> fetchURL(url2));
response.send(future1.get() + future2.get());
} catch (ExecutionException | InterruptedException e) {
response.fail(e);
}
}
String fetchURL(URL url) throws IOException {
try (var in = url.openStream()) {
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
}
三、总结
随着Java的发展,Java21发布集成了ProjectLoom,Java正式支持了虚拟线程。虚拟线程基本上会成为下一代Java性能爆发的利器。但是目前国内主流的服务器Java版本还停留在Java8版本,而国外基本上也停留在Java11版本。距离大家真正使用上虚拟现成可能还有一段时间。大家可以根据自己的项目环境,结合上面的技术提升现有的项目吞吐能力。