Java 线程池/阻塞队列疑问三连,请大佬解答!

2022-12-14 17:03:40 +08:00
 wangxin3
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5000), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

public static void main(String[] args) {
    List<Map<String, String>> list = new ArrayList<>();
    // add 5000 次
    list.add(new HashMap<>(16));

    list.forEach(l -> CompletableFuture.runAsync(() -> {
        System.out.println(l.get("xxx"));
        System.out.println(l.get("yyy"));
        // 又臭又长的代码 耗时 1s
    }, threadPoolExecutor));
    
    // 问:此时阻塞队列中任务内存占用主要来源于哪里?
    //    是遍历 list 出来的每个元素对象的占用内存吗?
    //    业务逻辑代码的长短 /复杂度会影响内存占用吗?
}
1858 次点击
所在节点    程序员
13 条回复
bootvue
2022-12-14 17:10:52 +08:00
没有大佬 可以配合 jprofile 分析下
guyeu
2022-12-14 17:22:33 +08:00
了解下引用和对象的概念呗
wangxin3
2022-12-14 17:35:29 +08:00
@guyeu #2 原文:“了解下引用和对象的概念呗”
======
回复:想了想,list 对象在进入阻塞队列之前已经存在于内存中了,所以线程池中的内存占用主要是来源于对象的地址,以及方法的地址?不知道是不是这样理解
wangxin3
2022-12-14 17:35:40 +08:00
@bootvue #1 原文:“没有大佬 可以配合 jprofile 分析下”
======
回复:get 新工具!
7911364440
2022-12-14 17:41:48 +08:00
线程池的内存占用取决于线程的数量,线程的内存占用取决于 run()方法中申请的内存空间,其实就是看你那段 "又臭又长的代码 耗时 1s" 的逻辑
wangxin3
2022-12-14 17:54:55 +08:00
@7911364440 #5 原文:“线程池的内存占用取决于线程的数量,线程的内存占用取决于 run()方法中申请的内存空间,其实就是看你那段 "又臭又长的代码 耗时 1s" 的逻辑”
======
回复:懂了,那按理来说线程池导致的 oom ,唯一的原因可能就是没有设置阻塞队列的长度?因为如果设置了长度,合理设置了 corePoolSize 、maximumPoolSize ,那么线程池多个线程在运行同一个方法时,因为单个方法的内存占用量是固定的,corePoolSize 是固定的,所以可以说线程池的内存占用量就是固定的。
线程池内存占用量 = corePoolSize * 单个方法的内存占用量(阻塞队列还没满时)
Yuesh1
2022-12-14 18:37:41 +08:00
突然想到,线程池本身也是一个对象,也需要内存占用,应该也有少量的内存消耗。
我理解的线程池 oom ,在合理设置了参数后,应该就是阻塞队列的 maxSize = Integer.MAX_VALUE 所导致的
期待其他大佬的见解
optional
2022-12-14 19:11:57 +08:00
你这里每个 map 对象每个对象都被 list 引用了,没有释放的机会;
另外()->{}会创建一个闭包对象。
chendy
2022-12-14 19:58:29 +08:00
> 此时阻塞队列中任务内存占用主要来源于哪里?

来源于 '阻塞别列中任务占用的内存'

> 是遍历 list 出来的每个元素对象的占用内存吗?

是 '每个元素对象的的占用的内存'

> 业务逻辑代码的长短 /复杂度会影响内存占用吗?

会,越慢堆积任务越多,越复杂当然也多
liprais
2022-12-14 20:30:23 +08:00
不要打印到标准输出,那上面有个锁
imv2er
2022-12-14 20:52:10 +08:00
我的能算标准答案么
//此时阻塞队列中任务内存占用主要来源于哪里?
map 中的 kv 元素数量
// 是遍历 list 出来的每个元素对象的占用内存吗?
是的
// 业务逻辑代码的长短 /复杂度会影响内存占用吗
会 ,因为这些逻辑代码中间几乎肯定会产生很多临时对象, 当然回收也很快。
wangxin3
2022-12-15 09:45:36 +08:00
@imv2er
@chendy
那么阻塞队列的阻塞的任务(没有运行的,正在排队的任务)内存占用量其实就是多线程任务的入参了吧。因为 corePoolSize 是固定的,阻塞队列是有设置大小的,所以就可以理解线程池的内存占用是固定的吧,或者说增长是微乎其微,因为只有基本类型和 String 的入参。
imv2er
2022-12-15 19:58:44 +08:00
@wangxin3 你等固定任务数是队列大小 /长度 但是你控制不了 map 中又多少元素。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/902519

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX