• 线程池中某个线程执行有异常,该如何处理?


    1. 线程池抛出异常代码

    class Task implements Runnable{
    
        @Override
        public void run() {
            System.out.println("task start...");
            int i = 1 / 0;
            System.out.println("task end...");
        }
    }
    
    class MyThreadFactoryTest implements ThreadFactory {
        private final AtomicInteger count = new AtomicInteger(0);
    
        @Override
        public Thread newThread(Runnable r) {
            int c = count.incrementAndGet();
            Thread t = new Thread(r);
            t.setName("MyThreadFactory.thread." + c);
            return t;
        }
    }
    
    public class Tmp {
    
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(1, new MyThreadFactoryTest());
            executorService.submit(new Task());
            executorService.execute(new Task());
            executorService.shutdown();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    输出:
    在这里插入图片描述

    executorService.submit 没有打印出异常

    使用future可以打印,如下
    在这里插入图片描述

    submit 底层仍然是执行execute,只不过封装了一层future,所以需要future.get()才能进行异常捕获和处理

    2. 如何获取和处理异常

    方法1: 线程自身打印异常

    在这里插入图片描述

    方法2: 使用Thread.setUncaughtExceptionHandler设置线程自己的异常处理

    如果要求每个任务都自主加上try ... catch...显然不太合适,无法要求每个人,就自己做改变吧…

    
    class Task implements Runnable{
    
        @Override
        public void run() {
            System.out.println("task start...");
            int i = 1 / 0;
            System.out.println("task end...");
        }
    }
    
    class MyThreadFactoryTest implements ThreadFactory {
        private final AtomicInteger count = new AtomicInteger(0);
    
        @Override
        public Thread newThread(Runnable r) {
            int c = count.incrementAndGet();
            Thread t = new Thread(r);
            t.setName("MyThreadFactory.thread." + c);
            t.setUncaughtExceptionHandler((thread, e)->{
                System.out.println("线程工厂设置ExceptionHandler:"+thread.getName() + ":" + e);
            });
            return t;
        }
    }
    
    public class Tmp {
    
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(1, new MyThreadFactoryTest());
            // 仍然无打印
            executorService.submit(new Task());
            // 被线程工厂设置ExceptionHandler捕获到异常
            executorService.execute(new Task());
            executorService.shutdown();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在这里插入图片描述

    附:java.util.concurrent.ThreadPoolExecutor#runWorker

    通过阅读源码,execute一个任务,如果能成功执行,会被封装成一个worker,然后执行runWorker方

    final void runWorker(Worker w) {
            Thread wt = Thread.currentThread();
            Runnable task = w.firstTask;
            w.firstTask = null;
            w.unlock(); // allow interrupts
            boolean completedAbruptly = true;
            try {
                while (task != null || (task = getTask()) != null) {
                    w.lock();
                    // If pool is stopping, ensure thread is interrupted;
                    // if not, ensure thread is not interrupted.  This
                    // requires a recheck in second case to deal with
                    // shutdownNow race while clearing interrupt
                    if ((runStateAtLeast(ctl.get(), STOP) ||
                         (Thread.interrupted() &&
                          runStateAtLeast(ctl.get(), STOP))) &&
                        !wt.isInterrupted())
                        wt.interrupt();
                    try {
                        beforeExecute(wt, task);
                        Throwable thrown = null;
                        try {
                            //线程执行 
                            task.run();
                            // 各种异常捕获
                        } catch (RuntimeException x) {
                            thrown = x; throw x;
                        } catch (Error x) {
                            thrown = x; throw x;
                        } catch (Throwable x) {
                            thrown = x; throw new Error(x);
                        } finally {
                        	// 执行完的处理,可以看到有补货到的异常
                            afterExecute(task, thrown);
                        }
                    } finally {
                        task = null;
                        w.completedTasks++;
                        w.unlock();
                    }
                }
                completedAbruptly = false;
            } finally {
                processWorkerExit(w, completedAbruptly);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    方法3: 重写线程池的afterExecute方法

    当然Thread.setUncaughtExceptionHandler仍然有效

    class Task implements Runnable{
    
        @Override
        public void run() {
            System.out.println("task start...");
            int i = 1 / 0;
            System.out.println("task end...");
        }
    }
    
    class MyThreadFactoryTest implements ThreadFactory {
        private final AtomicInteger count = new AtomicInteger(0);
    
        @Override
        public Thread newThread(Runnable r) {
            int c = count.incrementAndGet();
            Thread t = new Thread(r);
            t.setName("MyThreadFactory.thread." + c);
    
            return t;
        }
    }
    
    public class Tmp {
    
        public static void main(String[] args) {
            ExecutorService executorService =  new ThreadPoolExecutor(2, 10,
                    0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>(),
                    new MyThreadFactoryTest()){
                @Override
                protected void afterExecute(Runnable r, Throwable t) {
                    System.out.println("afterExecute:" + Thread.currentThread().getName() + ":" + t);
                }
            };
            // 仍然无打印
            executorService.submit(new Task());
            // 被线程工厂设置ExceptionHandler捕获到异常
            executorService.execute(new Task());
            executorService.shutdown();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    在这里插入图片描述

    submit的任务afterExecute单独内部判断处理

    在这里插入图片描述

  • 相关阅读:
    buuctf [BJDCTF2020]Easy MD5
    计算机组成体系
    解决Ubuntu无法安装pycairo和PyGObject
    云原生之路 | 1.快速了解容器(Container)及容器编排技术
    深入理解java和dubbo的SPI机制
    「KDOI」Round 2 | CSP-S 组模拟赛
    Android毕业设计开题报告基于Uniapp+SSM实现的公园植物介绍APP
    JAVA培训之数据库表关联关系
    HTTP/HTTPS和SOCKS5代理的区别
    Java基于SpringBoot的学生就业管理信息系统
  • 原文地址:https://blog.csdn.net/qq_26437925/article/details/127463372