线程不够用怎么办?

简介: ### 并发编程挑战与解决方案概览- 多线程导致线程爆炸,浪费CPU及可能导致JVM崩溃。线程池缓解问题,但仍有阻塞IO的效率低下。- 非阻塞IO(如servlet3.1/Tomcat)和事件驱动(Reactive/Future)减少线程使用,但学习曲线陡峭。- 轻量级线程如Netty、Spring Flux和虚拟线程(Java Loom)提升性能,但普及尚需时日。Java21引入虚拟线程,有望成未来性能关键。

一、同步并发编程困境-线程爆炸

为了提高系统利用率,进程发展到多线程,但是多线程并不完美
image.png

  1. 问题 1:线程等待或线程阻塞。CPU浪费。线程池满而拒绝服务。
  2. 问题 2:创建更多线程可能会导致 JVM 崩溃(内存不足)。每个线程大概需要占用1M内存。

一) 典型线程池应用

image.png

二、技术的发展和探索

一)提高线程利用率:阻塞IO和非阻塞IO

  1. 阻塞IO:image.png
  2. 非阻塞IO:image.png
  3. servlet3.1和tomcat对非阻塞IO的支持:image.png

二)减少线程使用(不阻塞线程):事件驱动, Reactive, Future

  1. 事件驱动:image.png
  2. Reactive响应式编程: image.png
  3. Spring Future异步方法编排: image.png

三)非阻塞NIO和事件驱动结合:Netty和HSF异步,HttpAsyncClient, 异步Tair

  1. Netty:image.png
  2. SpringFlux:image.png
  3. Apache的HttpAsyncClient
  4. Tair异步SDK

四)轻量级线程:纤程(Fiber),协程(coroutine),虚拟线程(VirtualThread)

异步响应式的问题:1. 需要学习一种新的编程模式,学习曲线略高。 2. 调用追踪困难。3. 只要有一个库不支持响应式就会导致响应式失效。

image.png

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版本。距离大家真正使用上虚拟现成可能还有一段时间。大家可以根据自己的项目环境,结合上面的技术提升现有的项目吞吐能力。

相关文章
|
弹性计算 安全 Linux
SSH 无法远程登录问题的处理思路
购买云服务器 ECS(后续简称 ECS)Linux 服务器后,首先面临的就是如何登录和使用的问题。而由于服务器在云端,所以日常运维中通常都会基于 SSH 客户端登录服务器进行相关操作。今天,我们就从登录 ECS 的不同方法和使用场景讲起,捋清 SSH 无法远程登录问题的常见原因与排查思路。
libfreetype.so.6: cannot open shared object file: No such file or directory
libfreetype.so.6: cannot open shared object file: No such file or directory
1266 0
|
10月前
|
数据采集 人工智能 数据可视化
SpatialLM:手机视频秒建3D场景!开源空间认知模型颠覆机器人训练
SpatialLM 是群核科技开源的空间理解多模态模型,能够通过普通手机拍摄的视频重建 3D 场景布局,赋予机器人类似人类的空间认知能力,适用于具身智能训练、自动导航、AR/VR 等领域。
859 5
SpatialLM:手机视频秒建3D场景!开源空间认知模型颠覆机器人训练
|
10月前
|
人工智能 监控 算法
Python下的毫秒级延迟RTSP|RTMP播放器技术探究和AI视觉算法对接
本文深入解析了基于Python实现的RTSP/RTMP播放器,探讨其代码结构、实现原理及优化策略。播放器通过大牛直播SDK提供的接口,支持低延迟播放,适用于实时监控、视频会议和智能分析等场景。文章详细介绍了播放控制、硬件解码、录像与截图功能,并分析了回调机制和UI设计。此外,还讨论了性能优化方法(如硬件加速、异步处理)和功能扩展(如音量调节、多格式支持)。针对AI视觉算法对接,文章提供了YUV/RGB数据处理示例,便于开发者在Python环境下进行算法集成。最终,播放器凭借低延迟、高兼容性和灵活扩展性,为实时交互场景提供了高效解决方案。
845 5
|
Web App开发 数据采集 存储
WebDriver与Chrome DevTools Protocol:如何在浏览器自动化中提升效率
本文探讨了如何利用Chrome DevTools Protocol (CDP) 与 Selenium WebDriver 提升浏览器自动化效率,结合代理IP技术高效采集微博数据。通过CDP,开发者可直接操作浏览器底层功能,如网络拦截、性能分析等,增强控制精度。示例代码展示了如何设置代理IP、cookie及user-agent来模拟真实用户行为,提高数据抓取成功率与稳定性。适用于需要频繁抓取互联网数据的应用场景。
1434 3
WebDriver与Chrome DevTools Protocol:如何在浏览器自动化中提升效率
针对报错:java.lang.Integer cannot be cast to java.lang.Long..的解决办法
针对报错:java.lang.Integer cannot be cast to java.lang.Long..的解决办法
5040 0
针对报错:java.lang.Integer cannot be cast to java.lang.Long..的解决办法
|
消息中间件 存储 Java
MQ核心作用、解耦、削峰使用场景详解
【11月更文挑战第21天】在如今的高并发互联网应用中,如何确保系统在巨大的流量冲击下还能稳定运行,是每个技术团队都会遇到的挑战。说到这,消息队列(MQ)就是背后的“大功臣”了。无论是异步处理请求、平滑应对流量高峰,还是让各个系统模块相互独立不“拖后腿”,MQ都是不可或缺的帮手。那么,MQ是如何削峰的?或者它是如何让复杂系统解耦的?今天,我们就来聊聊MQ的三大核心功能,看它是如何助力系统高效、稳定运转的。
899 1
|
存储 缓存 安全
java锁优化高频面试题(真实面试经历总结)
java锁优化高频面试题(真实面试经历总结)
|
安全 数据库连接 数据库
(六)手撕并发编程之基于Semaphore与CountDownLatch分析AQS共享模式实现
在上篇文章《深入剖析并发之AQS独占锁&重入锁(ReetrantLock)及Condition实现原理》中我们曾基于ReetrantLock锁分析了AQS独占模式的实现原理,本章则准备从Semaphore信号量的角度出发一探AQS共享模式的具体实现。共享模式与独占模式区别在于:共享模式下允许多条线程同时获取锁资源,而在之前分析的独占模式中,在同一时刻只允许一条线程持有锁资源。
155 1
|
Java API 存储
Java如何对List进行排序?
【7月更文挑战第26天】
1594 9
Java如何对List进行排序?