同一个线程池嵌套使用程序卡死问题排查

本文探讨了在Spring应用中,如何因使用同一线程池导致外层任务与内层任务资源竞争,形成死锁,通过代码示例和JStack分析揭示问题本质并提供解决策略。

这是一个开发中遇到的一个问题,场景是单次http请求需要调用很多次上游接口,所以采用线程池并发调用。开发中没有注意,外层任务和内层任务都是用了线程池,并且使用的是同一个线程池,造成了资源竞争,外层需要内层执行结束的结果,内层需要外层释放的线程,两者相持不下,造成程序卡死。

用代码模拟个场景,同一个线程池,submit一个任务之后,又在任务中submit一个新的线程任务。这里定一个只有一个核心线程数的线程池,用于展示现象,并不特指只有单线程才会出现bug现象。

package com.example.springdemo;

import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.concurrent.*;

public class TestA {
    private static ThreadPoolExecutor es = new ThreadPoolExecutor(1, 1,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(), new CustomizableThreadFactory("test-thread-"), new ThreadPoolExecutor.CallerRunsPolicy());

    /*private static ThreadPoolExecutor esIn = new ThreadPoolExecutor(2, 2,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(), new CustomizableThreadFactory("test-thread-in-"), new ThreadPoolExecutor.CallerRunsPolicy());*/

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //商品信息
        System.out.println("商品信息查询开始");
        Future<?> fProduct = es.submit(() -> {
            //这里需要组装两部分信息 1是基本信息 2是促销信息
            //为了加快速度,促销信息用一个新线程查,基本信息用当前线程查
            Future<?> fPromo = es.submit(() -> {
                System.out.println("这句代表查询了商品促销信息接口");
            });
            System.out.println("这句代表查询了商品基本信息接口");
            try {
                fPromo.get();
                System.out.println("基本信息和促销信息都拿到了");
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
        fProduct.get();
        System.out.println("商品信息查询结束");
    }

}

调试运行,结果是只打印了两句。基本可以证明查询促销任务没有执行(因为没有打印执行的文案)。

 更加

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值