V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
3country
V2EX  ›  程序员

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

  •  
  •   3country · 2024-09-03 10:44:06 +08:00 · 2186 次点击
    这是一个创建于 379 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码逻辑如下:

    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 的逻辑,有大佬给点排查思路吗

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

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

    1. 确定 main 里面等待 executorService 执行完
    2. 任务里面用 try-catch 包住,记录异常
    MozzieW
        8
    MozzieW  
       2024-09-03 11:21:52 +08:00
    1. 直接点,多加日志,try catch ,看能不能找到问题
    2. 喝口水,上个厕所,回来代码多看几次
    lujianwen9
        9
    lujianwen9  
       2024-09-03 11:40:54 +08:00
    executorService 没加异常处理吧
    AlanBrian
        10
    AlanBrian  
       2024-09-03 11:50:14 +08:00
    没有异常处理不会输出到日志文件的
    ArthurTsang
        11
    ArthurTsang  
       2024-09-03 11:52:25 +08:00
    子线程 catch 下异常吧
    fengpan567
        12
    fengpan567  
       2024-09-03 11:55:03 +08:00
    为啥不先看看 error 日志
    magicZ
        13
    magicZ  
       2024-09-03 13:22:24 +08:00
    我也这么干过跑数据,比这个还粗暴直接 new 了 30 个线程跑,跑完生成文件。然后第二天我发现有几个文件没生成,也没有异常日志,检查几遍后发现就是 try catch 没指定的异常不对(代码自动生成的 IOException, 实际是 NPE 报错),导致线程挂了也没报错。
    magicZ
        14
    magicZ  
       2024-09-03 13:27:14 +08:00
    @magicZ 用了线程池有返回值异常在 future.get()时触发,无返回值,你的 AsyncUncaughtExceptionHandler 有没有拦截异常
    diagnostics
        15
    diagnostics  
       2024-09-03 14:05:57 +08:00
    OOM 这类异常,可能就挂掉了,你只 Catch Exception 是不够的,我见过我同事,LogBack 不记录 fatal error 日志,排查半天才知道线程挂了
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5142 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 93ms · UTC 08:59 · PVG 16:59 · LAX 01:59 · JFK 04:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.