CompletableFuture.allOf().get()引起的线程池死锁

news2024/11/26 12:17:59

CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(completableFutures);可以同步等待一组异步请求都返回结果后,再往下执行。voidCompletableFuture.get()会同步等待所有结果返回,并且不会超时。就因为没有设置超时时间,造成了死锁的发生。

这是发生死锁的代码:

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池死锁案例
 */
public class ThreadPoolTest {
    /**
     * 线程池
     */
    public static ThreadPoolExecutor THREAD_POOL = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), r -> new Thread(r, "THREAD_POOL_TEST"));

    public static void main(String[] args) throws InterruptedException {
        AtomicInteger atomicInteger = new AtomicInteger();
        for (int i = 0; i < 10; i++) {
            THREAD_POOL.submit(() -> {
                System.out.println("run task" + atomicInteger.getAndIncrement());
                executeSubTask();
            });
        }
        Thread.sleep(1000);

        System.out.println("task count: " + THREAD_POOL.getTaskCount());
        System.out.println("task in queue count: " + THREAD_POOL.getQueue().size());
    }

    private static void executeSubTask() {
        CompletableFuture[] completableFutures = new CompletableFuture[6];
        AtomicInteger atomicInteger = new AtomicInteger();
        for (int i = 0; i < 6; i++) {
            CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
                System.out.println("ok-" + atomicInteger.getAndIncrement());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                return "ok:" + atomicInteger.get();
            }, THREAD_POOL);
            completableFutures[i] = task;
        }
        System.out.println("submit subTask size:" + completableFutures.length);
        try {
            CompletableFuture.allOf(completableFutures).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
    }
}

处理逻辑是:

  1. 异步执行父任务

  2. 父任务里包含多个子任务

为了异步执行任务,所以放到线程池THREAD_POOL里。然后,任务里包含多个子任务,为了降低执行时间,把子任务做成了并发执行,使用了CompletableFuture.allOf(completableFutures).get()方法。

get()一般都会设置超时时间,但是因为异步任务设置了超时时间,所以就没再单独设置get()的超时时间,就引发了线程池死锁发生。

原因分析

子任务执行较慢,线程池的核心线程马上被父任务占满(5个)。父任务里提交的子任务都跑到阻塞队里里,等待核心线程来调度任务。核心线程又阻塞在CompletableFuture.allOf(completableFutures).get()这里,任务无法结束。

线程池状态

5个线程都处于WAITING状态,阻塞在 at java.util.concurrent.CompletableFuture.get(java.base@17/CompletableFuture.java:2072)

"THREAD_POOL_TEST" #12 prio=5 os_prio=0 cpu=4.14ms elapsed=485.93s tid=0x00007f64a448fcf0 nid=0x23b2 waiting on condition  [0x00007f648c1fa000]
   java.lang.Thread.State: WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base@17/Native Method)
        - parking to wait for  <0x00000000e37436b0> (a java.util.concurrent.CompletableFuture$Signaller)
        at java.util.concurrent.locks.LockSupport.park(java.base@17/LockSupport.java:211)
        at java.util.concurrent.CompletableFuture$Signaller.block(java.base@17/CompletableFuture.java:1864)
        at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@17/ForkJoinPool.java:3463)
        at java.util.concurrent.ForkJoinPool.managedBlock(java.base@17/ForkJoinPool.java:3434)
        at java.util.concurrent.CompletableFuture.waitingGet(java.base@17/CompletableFuture.java:1898)
        at java.util.concurrent.CompletableFuture.get(java.base@17/CompletableFuture.java:2072)
        at ThreadPoolTest.executeSubTask(ThreadPoolTest.java:45)
        at ThreadPoolTest.lambda$main$1(ThreadPoolTest.java:19)
        at ThreadPoolTest$$Lambda$237/0x0000000800d54428.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(java.base@17/Executors.java:539)
        at java.util.concurrent.FutureTask.run(java.base@17/FutureTask.java:264)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17/ThreadPoolExecutor.java:1136)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17/ThreadPoolExecutor.java:635)
        at java.lang.Thread.run(java.base@17/Thread.java:833)

"THREAD_POOL_TEST" #13 prio=5 os_prio=0 cpu=0.54ms elapsed=485.93s tid=0x00007f64a4490b70 nid=0x23b3 waiting on condition  [0x00007f647dffe000]
   java.lang.Thread.State: WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base@17/Native Method)
        - parking to wait for  <0x00000000e375c280> (a java.util.concurrent.CompletableFuture$Signaller)
        at java.util.concurrent.locks.LockSupport.park(java.base@17/LockSupport.java:211)
        at java.util.concurrent.CompletableFuture$Signaller.block(java.base@17/CompletableFuture.java:1864)
        at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@17/ForkJoinPool.java:3463)
        at java.util.concurrent.ForkJoinPool.managedBlock(java.base@17/ForkJoinPool.java:3434)
        at java.util.concurrent.CompletableFuture.waitingGet(java.base@17/CompletableFuture.java:1898)
        at java.util.concurrent.CompletableFuture.get(java.base@17/CompletableFuture.java:2072)
        at ThreadPoolTest.executeSubTask(ThreadPoolTest.java:45)
        at ThreadPoolTest.lambda$main$1(ThreadPoolTest.java:19)
        at ThreadPoolTest$$Lambda$237/0x0000000800d54428.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(java.base@17/Executors.java:539)
        at java.util.concurrent.FutureTask.run(java.base@17/FutureTask.java:264)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17/ThreadPoolExecutor.java:1136)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17/ThreadPoolExecutor.java:635)
        at java.lang.Thread.run(java.base@17/Thread.java:833)

"THREAD_POOL_TEST" #15 prio=5 os_prio=0 cpu=1.30ms elapsed=485.92s tid=0x00007f64a4491b70 nid=0x23b4 waiting on condition  [0x00007f647defd000]
   java.lang.Thread.State: WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base@17/Native Method)
        - parking to wait for  <0x00000000e377bef8> (a java.util.concurrent.CompletableFuture$Signaller)
        at java.util.concurrent.locks.LockSupport.park(java.base@17/LockSupport.java:211)
        at java.util.concurrent.CompletableFuture$Signaller.block(java.base@17/CompletableFuture.java:1864)
        at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@17/ForkJoinPool.java:3463)
        at java.util.concurrent.ForkJoinPool.managedBlock(java.base@17/ForkJoinPool.java:3434)
        at java.util.concurrent.CompletableFuture.waitingGet(java.base@17/CompletableFuture.java:1898)
        at java.util.concurrent.CompletableFuture.get(java.base@17/CompletableFuture.java:2072)
        at ThreadPoolTest.executeSubTask(ThreadPoolTest.java:45)
        at ThreadPoolTest.lambda$main$1(ThreadPoolTest.java:19)
        at ThreadPoolTest$$Lambda$237/0x0000000800d54428.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(java.base@17/Executors.java:539)
        at java.util.concurrent.FutureTask.run(java.base@17/FutureTask.java:264)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17/ThreadPoolExecutor.java:1136)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17/ThreadPoolExecutor.java:635)
        at java.lang.Thread.run(java.base@17/Thread.java:833)

"THREAD_POOL_TEST" #14 prio=5 os_prio=0 cpu=1.08ms elapsed=485.92s tid=0x00007f6454002a90 nid=0x23b5 waiting on condition  [0x00007f647ddfc000]
   java.lang.Thread.State: WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base@17/Native Method)
        - parking to wait for  <0x00000000e379a918> (a java.util.concurrent.CompletableFuture$Signaller)
        at java.util.concurrent.locks.LockSupport.park(java.base@17/LockSupport.java:211)
        at java.util.concurrent.CompletableFuture$Signaller.block(java.base@17/CompletableFuture.java:1864)
        at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@17/ForkJoinPool.java:3463)
        at java.util.concurrent.ForkJoinPool.managedBlock(java.base@17/ForkJoinPool.java:3434)
        at java.util.concurrent.CompletableFuture.waitingGet(java.base@17/CompletableFuture.java:1898)
        at java.util.concurrent.CompletableFuture.get(java.base@17/CompletableFuture.java:2072)
        at ThreadPoolTest.executeSubTask(ThreadPoolTest.java:45)
        at ThreadPoolTest.lambda$main$1(ThreadPoolTest.java:19)
        at ThreadPoolTest$$Lambda$237/0x0000000800d54428.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(java.base@17/Executors.java:539)
        at java.util.concurrent.FutureTask.run(java.base@17/FutureTask.java:264)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17/ThreadPoolExecutor.java:1136)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17/ThreadPoolExecutor.java:635)
        at java.lang.Thread.run(java.base@17/Thread.java:833)

"THREAD_POOL_TEST" #16 prio=5 os_prio=0 cpu=0.33ms elapsed=485.92s tid=0x00007f645c001250 nid=0x23b6 waiting on condition  [0x00007f647dcfb000]
   java.lang.Thread.State: WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base@17/Native Method)
        - parking to wait for  <0x00000000e37b83f8> (a java.util.concurrent.CompletableFuture$Signaller)
        at java.util.concurrent.locks.LockSupport.park(java.base@17/LockSupport.java:211)
        at java.util.concurrent.CompletableFuture$Signaller.block(java.base@17/CompletableFuture.java:1864)
        at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@17/ForkJoinPool.java:3463)
        at java.util.concurrent.ForkJoinPool.managedBlock(java.base@17/ForkJoinPool.java:3434)
        at java.util.concurrent.CompletableFuture.waitingGet(java.base@17/CompletableFuture.java:1898)
        at java.util.concurrent.CompletableFuture.get(java.base@17/CompletableFuture.java:2072)
        at ThreadPoolTest.executeSubTask(ThreadPoolTest.java:45)
        at ThreadPoolTest.lambda$main$1(ThreadPoolTest.java:19)
        at ThreadPoolTest$$Lambda$237/0x0000000800d54428.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(java.base@17/Executors.java:539)
        at java.util.concurrent.FutureTask.run(java.base@17/FutureTask.java:264)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17/ThreadPoolExecutor.java:1136)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17/ThreadPoolExecutor.java:635)
        at java.lang.Thread.run(java.base@17/Thread.java:833)

解决方案

  1. 父任务和子任务使用单独的线程池,避免出现循环依赖

  2. 设置超时时间,CompletableFuture.allOf(completableFutures).get(3, TimeUnit.SECONDS)

另外,任务子任务数量比较多,就需要更多的线程去执行,5个核心线程数量就不够了。但加大核心线程数,对于突发类型的任务,空闲时又浪费线程。我们就可以设置更大核心线程的同时,并设置核心线程在超时时可以回收。

public static ThreadPoolExecutor THREAD_POOL = new ThreadPoolExecutor(20, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), r -> new Thread(r, "THREAD_POOL_TEST"));
// 回收核心线程
THREAD_POOL.allowCoreThreadTimeOut(true);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2063199.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入浅出,探讨IM(即时通讯-聊天工具)技术架构及用户界面设计

在数字化时代的浪潮中&#xff0c;即时通讯&#xff08;IM&#xff09;工具已然成为人们日常沟通的重要方式。从微信、QQ到飞信钉、喧喧IM、企业微信、钉钉、Slack&#xff0c;这些IM工具不仅为我们提供了便捷的沟通方式&#xff0c;更在技术架构和用户界面设计上展现了独特的魅…

WPF中如何使用后台代码动态创建数据模板(DataTemplate)

数据模板回顾 在WPF中数据模板可以控制数据的呈现方式。 对于一些简单的数据&#xff0c;例如一个string&#xff0c;一个int&#xff0c;在显示时&#xff0c;无须额外控制 。 但是对于复杂数据类型&#xff0c;就需要使用数据模板来控制数据的呈现方式。 一个简单的例子 …

熟悉Labview工具用

目录复制 目录 0.0&#xff1a;快捷键0.1&#xff1a;全局非图标显示0.2&#xff1a;小技巧&#xff1a;图片导入为程序1.2&#xff1a;事件结构1.2.0&#xff1a;超时分支&#xff1a;当事件结构框左上角设置为1时&#xff0c;单位毫秒&#xff0c;即理解为1ms内没有其他的事件…

Redis远程字典服务器(10)—— 渐进式命令与数据库管理命令

一&#xff0c;关于渐进式命令 我们之前讲过keys命令&#xff0c;可以把一次性把整个Redis的所有key都获取到&#xff0c;所以这个操作比较“危险”&#xff0c;可能会一下子得到太多的key&#xff0c;从而阻塞Redis服务器通过渐进式命令&#xff0c;就能做到&#xff1a;既能…

高质量翻译对确保中国开发者获得高质量、高质量体验的影响

在全球市场上&#xff0c;中国开发商越来越努力地通过他们的游戏、应用程序和软件产品吸引国际观众。为了取得成功&#xff0c;这些产品必须具有功能性和创新性&#xff0c;并提供无缝、精致的体验&#xff0c;与全球用户产生共鸣。实现这一目标的一个关键组成部分是高质量的翻…

Gartner发布2024年中国安全技术成熟度曲线:17项网络安全技术发展和应用现状及趋势

采用生成式人工智能等颠覆性技术需要增加安全投资&#xff0c;而中国企业仍然面临预算限制。首席信息官及其安全和风险管理主管可以使用此技术成熟度曲线来识别和采用合适的安全实践。 需要知道什么 2024 年&#xff0c;在中国运营的企业将继续面临预算限制。预算平均增长2.8%…

滑动输入条、进度条

参考: Antdv Slider 滑动输入条Element Plus Progress 进度条 开发时遇到一个需求&#xff0c;一个进度条控制多个视频播放器。正常使用一些组件库自带的组件就好了——antdv的slider 但是使用change事件的话&#xff0c;使用拖拽进度点改变进度条value 就会频繁触发&#x…

C++版设计模式简介 与 初识 工厂模式

目录 前言 一、设计模式简介1. 什么是设计模式2. 设计模式分类3. 设计模式的优点4. 设计模式的实践 二、单例模式1. 单例模式的关键点2. 单例模式的实现方式饿汉式单例&#xff08;Eager Initialization&#xff09;懒汉式单例&#xff08;Lazy Initialization&#xff09;双重…

使用Ollama本地离线体验SimpleRAG(手把手教程)

Ollama介绍 Ollama是一个开源项目&#xff0c;专注于开发和部署大语言模型&#xff0c;特别是像LLaMA这样的模型&#xff0c;用于生成高质量的文本和进行复杂的自然语言处理任务。Ollama的目标是让大语言模型的运行和使用变得更加容易和普及&#xff0c;而无需复杂的基础设施或…

解决执行npm run dev报错node: --openssl-legacy-provider is not allowed in NODE_OPTIONS

问题&#xff1a; 最近下载了一个开源系统&#xff0c;执行npm install很顺利&#xff0c;以为大功告成&#xff0c;结果运行npm run dev时报错node: --openssl-legacy-provider is not allowed in NODE_OPTIONS 解决方法&#xff1a; 应用程序配置&#xff08;package.json&a…

在控件graphicsView中实现绘图功能(三)

这里写自定义目录标题 前言&#xff1a;效果展示&#xff1a;1.图片展示2.视频展示 基础夯实&#xff1a;一.文本框焦点&#xff1a;二.QGraphicsItems&#xff1a;1.QGraphicsRectItem2.QGraphicsLineItem3.QGraphicsEllipseItem4.QGraphicsTextItem5.QGraphicsPathItem 三.鼠…

KI-DDI:知识图谱 + 大模型 + 图注意力,医学诊断

KI-DDI&#xff1a;知识图谱 大模型 图注意力&#xff0c;医学诊断 具体到点精细分析对话处理 SapBERT医学知识处理 - 图注意力网络(GAT)信息融合 - 对话嵌入 - 知识图谱嵌入知识图谱的权重 KI-DDI 图分析性关联图 知识图谱 大模型 VS KI-DDI更强的个性化 论文&#xff1a;T…

[数据集][目标检测]街灯路灯检测数据集VOC+YOLO格式1893张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1893 标注数量(xml文件个数)&#xff1a;1893 标注数量(txt文件个数)&#xff1a;1893 标注…

adaptive AUTOSAR UCM模块中SoftwareCluster与Software Package是什么样的关系,他们分别包含哪些元素?

在自适应AUTOSAR(Adaptive AUTOSAR)的更新和配置管理(UCM)模块中,SoftwareCluster和Software Package是软件更新过程中的两个关键概念,它们之间有着密切的关系: SoftwareCluster:通常指的是一组功能相关的软件组件,它们共同实现了车辆中的一个或多个特定功能。在UCM中…

钓鱼的常见几种方式

钓鱼的多种方式 office钓鱼攻击 宏与宏病毒 # 宏 宏是office自带的一种高级脚本特性&#xff0c;通过VBA代码&#xff0c;可以在office中去完成某项特定的任务&#xff0c;而不必再重复相同的动作&#xff0c;目的是让用户文档中一些任务自动化# 宏病毒 宏病毒是一种寄存在文…

Qt实现圆型控件的三种方法之设置样式表

前言 最近在研究绘制各种形状的控件&#xff0c;这里专门挑出圆形的控件进行记录&#xff0c;其它形状的也大差不差&#xff0c;会了圆形的之后其它的也类似。 正文 这里我挑出Label来进行举例。 通过设置样式表 (QSS) 这种方法简单且适用于不需要自定义绘制的场景。就是要…

uniapp实现应用内检测版本更新(Android直接下载/ios跳转app store)

背景&#xff1a;最近需要给app加一个可以检测到新版本并更新的功能&#xff0c; 之前没有考虑过这个问题&#xff0c;第一次尝试&#xff0c;特此记录一下。 我在这里使用到了uniapp上的更新插件&#xff0c;并在此插件基础上进行更改以适应我的项目。 插件链接&#xff1a;ht…

【专题】2023-2024中国游戏企业研发竞争力报告合集PDF分享(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p37447 在当今的数字时代&#xff0c;游戏产业已然成为经济与文化领域中一股不可忽视的重要力量。2023 年&#xff0c;中国自研游戏市场更是呈现出一片繁荣且复杂的景象&#xff0c;实际销售收入达到了令人瞩目的 2563.8 亿元&#x…

计算机毕业设计选题推荐-民宿可视化分析-Python爬虫-随机森林算法

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

Catf1ag CTF Web(九)

前言 Catf1agCTF 是一个面向所有CTF&#xff08;Capture The Flag&#xff09;爱好者的综合训练平台&#xff0c;尤其适合新手学习和提升技能 。该平台由catf1ag团队打造&#xff0c;拥有超过200个原创题目&#xff0c;题目设计注重知识点的掌握&#xff0c;旨在帮助新手掌握C…