长连接中异步任务的同步等待陷阱:一次主线程阻塞的排查与修复

最近的项目出现了一个bug,长连接中使用了异步线程池,具体是有一个循环,每一次循环都用了异步线程,然后呢,在长连接中处理这个循环的同时,还会有前端向后端发送消息,那么后端也要接收相应的消息进行处理,每次循环的异步线程如下

java 复制代码
Future<Boolean> submit = taskExecutor.submit(new Callable<Boolean>() {
                @Override
                public Boolean call(){}
                });

然后呢还搞了一个

java 复制代码
private final Map<String, Future<Boolean>> Futures = new ConcurrentHashMap<>();
Futures.put(id, submit);

以id为key保存每一次循环中的异步线程返回值,然后呢,最灵魂的代码来喽,这句代码真是给添了不少麻烦,那就是等待这次异步任务完成,实际上大错特错

java 复制代码
Future<Boolean> future = Futures.get(id);
Boolean b = future.get();

这句代码乍一看倒是没什么问题,但是呢,在运行的时候,前端向后端发送特定的消息,后端没有响应,哇靠,这是为啥嘞?

没错,就是Boolean b = future.get();把主线程给阻塞了,导致不能处理其他问题,其实这只是一个小问题哈,但是有时候往往是小问题在写代码的时候,加着加着就忘记了,结果排查的时候好半天才看到。

最后的解决办法是啥呢,最后搞了一个异步线程处理这个循环,大致的代码示意如下:

java 复制代码
 CompletableFuture.runAsync(()->
    {
        for (dto:list) {
            Future<Boolean> submit = taskExecutor.submit(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                }
            });
        }
    })
相关推荐
Peregrine97 小时前
C++ - > 类和对象
java·c++·算法
2501_933923257 小时前
SpringCloud组件:Eureka服务注册与发现
java·开发语言·后端·spring cloud·eureka
Wang's Blog7 小时前
Java 中间件之 RabbitMQ 快速入门: SpringAMQP 消息转换器
java·中间件·java-rabbitmq
Re_zero8 小时前
一次 SSE 断流排查:PrintWriter 吞掉了我的 IOException
java·后端
我是人✓8 小时前
Java核心语法:作用域、循环与大数值处理
java·开发语言·后端
夜之眷属9 小时前
PriorityQueue:for-each 遍历和 poll 取出,顺序一样吗?
java·服务器·数据结构·后端·算法
蜗牛互联网9 小时前
Java标准HTTP调用多模态模型的票据抽取前置校验
java·人工智能·python·http
工具派9 小时前
Agent 不是玄学:用 Java 状态机思维理解 LangGraph
java·人工智能·python
十年Java程序媛10 小时前
String / StringBuilder / StringBuffer|别再乱用字符串拼接,底层原理一次讲透
java·spring boot·后端
傲世仙尊10 小时前
类和对象中-构造函数与析构函数把初始化清理自动化
java·运维·自动化