请教一个 Java 线程池问题,子线程会自己挂掉吗?

2024-09-03 10:44:06 +08:00
 3country

代码逻辑如下:

public void fun() {
        List<Integer> list = new ArrayList<>();
        for(int i = 1; i <= 12345; i++) {
            list.add(i);
        }
        int total = list.size();
        int batchSize = total / 3;
        List<List<Integer>> partition = Lists.partition(list, batchSize);
        for (List<Integer> itemList : partition) {
            executorService.execute(() -> subFun(itemList));
        }
    }

    private void subFun(List<Integer> list) {
        String threadName = Thread.currentThread().getName();
        log.info("子线程{}开始执行。。。", threadName);
        for (Integer i : list) {
            .....
        }
        log.info("子线程{}执行总数:{}", threadName, list.size());
    }

总结就是将数据分为 3 块,并行执行,最终的日志结果是,子线程有 3 个开始执行了,却只有 2 个执行完,日志里没有异常信息,方法里也没有 return 的逻辑,有大佬给点排查思路吗

2203 次点击
所在节点    程序员
15 条回复
cJ8SxGOWRH0LSelC
2024-09-03 10:48:06 +08:00
你是跑的单元测试吗? 是不是因为主线程在子线程完成之前结束了, 导致进程停了。 可以在主线程尾部加个 sleep
3country
2024-09-03 10:51:26 +08:00
@StinkyTofus 拿单元测试做了个例子,实际是晚上跑的定时任务
cJ8SxGOWRH0LSelC
2024-09-03 10:53:25 +08:00
除了我上面说的可能性, 就是你 executorService 的队列设置的太小了, 超过的任务被丢弃了。 正常的情况下子线程肯定会被执行, 没有抛出异常的情况下,不会自己挂掉。
3country
2024-09-03 10:55:42 +08:00
@StinkyTofus log.info("子线程{}开始执行。。。", threadName)这一行代码每一个子线程都执行了,我感到疑惑的是为什么有一个线程没有执行完方法,也没有异常信息
cJ8SxGOWRH0LSelC
2024-09-03 10:58:19 +08:00
@3country #4 不是都说了么,你跑的单元测试不能验证你提出的问题, 主线程提前结束了, 加个 sleep 就行了。
cmai
2024-09-03 11:01:36 +08:00
怎么确定的没有异常信息?我看你方法里也没有 try catch
sagaxu
2024-09-03 11:09:47 +08:00
子线程不会自己挂掉。

executorService 可以是 daemon 也可以是非 daemon ,当他为 daemon 时,main 线程退出时,JVM 进程会结束,executorService 可能执行不完。

1. 确定 main 里面等待 executorService 执行完
2. 任务里面用 try-catch 包住,记录异常
MozzieW
2024-09-03 11:21:52 +08:00
1. 直接点,多加日志,try catch ,看能不能找到问题
2. 喝口水,上个厕所,回来代码多看几次
lujianwen9
2024-09-03 11:40:54 +08:00
executorService 没加异常处理吧
AlanBrian
2024-09-03 11:50:14 +08:00
没有异常处理不会输出到日志文件的
ArthurTsang
2024-09-03 11:52:25 +08:00
子线程 catch 下异常吧
fengpan567
2024-09-03 11:55:03 +08:00
为啥不先看看 error 日志
magicZ
2024-09-03 13:22:24 +08:00
我也这么干过跑数据,比这个还粗暴直接 new 了 30 个线程跑,跑完生成文件。然后第二天我发现有几个文件没生成,也没有异常日志,检查几遍后发现就是 try catch 没指定的异常不对(代码自动生成的 IOException, 实际是 NPE 报错),导致线程挂了也没报错。
magicZ
2024-09-03 13:27:14 +08:00
@magicZ 用了线程池有返回值异常在 future.get()时触发,无返回值,你的 AsyncUncaughtExceptionHandler 有没有拦截异常
diagnostics
2024-09-03 14:05:57 +08:00
OOM 这类异常,可能就挂掉了,你只 Catch Exception 是不够的,我见过我同事,LogBack 不记录 fatal error 日志,排查半天才知道线程挂了

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

https://ex.noerr.eu.org/t/1069826

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

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

© 2021 V2EX