程序员日常-------无法创建线程故障排查

本文详细描述了一个生产环境中遇到的问题,即消息队列中的消息无法被消费。经过调查,发现由于频繁创建线程导致线程资源耗尽,最终引发`OutOfMemoryError`。解决方案包括避免频繁创建线程和修复异常处理,确保异常发生时正确关闭循环。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:
        最近在工作中查了一个问题,消费者队列里面的消息无法没有成功消费。

问题描述:

        这里生产者会将消息放入队列中,由消费者消费消息。startLoop是一个消费者。

在生产环境中发现依然有生产者往队列里面发送消息,但是就是没有消费。

 private AtomicBoolean isLooping = new AtomicBoolean(false);
    private BlockingQueue<T> queue = new LinkedBlockingQueue<>(50000);
 public boolean add(T t) {
        try {
            queue.put(t);
            if (!isLooping.get()) {
                isLooping.set(true);
                startLoop();
            }
            return true;
        } catch (Exception e) {
            logger.error(this, e);
        }
        return false;
    }
private void startLoop() {
        new Thread(() -> {
            start = new AtomicLong(System.currentTimeMillis());
            while (true) {
                try {
                    long last = System.currentTimeMillis() - start.get();
                    if (processEnabled && (queue.size() >= batchSize || (!queue.isEmpty() && last > timeoutInMs))) {
                        drainToConsume();
                    } else if (queue.isEmpty()) {
                        isLooping.set(false);
                        break;
                    }
                } catch (Throwable e) {
                    logger.error("Batch process with error.", e);
                    isLooping.set(false);
                    break;
                }
            }
        }, this.name + BATCH_COMMIT_THREAD).start();

问题研究:
首先查看jstack日志:

 可以发现这里发生了阻塞。BatchQueue里面是一个阻塞队列,通过debug查看到队列的大小达到最大了,说明islooping为ture。走查了startLoop的代码,只要走到这里面,islooping最后肯定会被设置成fasle。除非这个线程就没有启动起来(排查的时候觉得基本不可能啊,哪有线程没有启动的现象)

继续研究jstack日志:

发现有4000多个线程abc_xxx这种,通过走查代码,发现有一个地方在频繁创建线程。最后导致线程数量不够用,java.lang.OutOfMemoryError: unable to create new native thread出现了这个异常,但是我们的异常没有捕获成功。

至此,问题已经找到

问题修复:
1 业务侧一定不能出现频繁创建线程的代码

2 修复代码中的Exception。并且抛异常后修改为是否循环修改为false

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值