引言
在Java多线程编程中,线程池是提高性能和资源利用率的常用工具。然而,当父子任务使用同一线程池时,可能导致潜在的死锁问题。本文将深入分析一个实际案例,阐述为何这种设计可能引发死锁,以及如何排查这类问题。
案例背景
考虑以下的伪代码,展示了一个可能导致死锁的场景:
代码语言:javascript复制java 代码解读复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Scratch {
private static final ExecutorService pool1 = Executors.newFixedThreadPool(2);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 50; i ) {
pool1.submit(() -> {
// 一些任务逻辑
outerTask();
});
}
try {
boolean allDone = pool1.awaitTermination(10000, TimeUnit.MILLISECONDS);
if (allDone) {
System.out.println("任务完成!");
} else {
System.err.println("任务超时未完成!");
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private static void outerTask() {
Future<?> future = pool1.submit(() -> {
innerTask();
});
try {
// 获取结果
future.get();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void innerTask() {
// 一些任务逻辑
}
}
简单解释下这个代码, 我们有一个固定线程数大小为2的线程池, 然后向线程池提交任务, 这个任务直接调用outerTask, 这个outerTask不做任何事情, 只通过线程池异步调用innerTask, 但是注意这里使用了同一个线程池提交innerTask.
最后通过awaitTermination等待线程池执行完毕线程终止就结束, 设置了超时10s, 如果任务都完成了打印"任务完成"否则打印"任务超时未完成", 而由于outerTask和innerTask内部都没有其他逻辑, 理论上应该是很快执行完毕, 打印"任务完成", 但实际如何呢, 执行一下, 结果是:
代码语言:javascript复制 代码解读复制代码任务超时未完成!
好, 这是肯定的