这是一个开发中遇到的一个问题,场景是单次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("商品信息查询结束");
}
}
调试运行,结果是只打印了两句。基本可以证明查询促销任务没有执行(因为没有打印执行的文案)。
更加

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

1397

被折叠的 条评论
为什么被折叠?



