美文网首页Java工程师知识树
Java基础-线程-线程的异常处理

Java基础-线程-线程的异常处理

作者: HughJin | 来源:发表于2021-02-01 07:30 被阅读0次

    Java工程师知识树 / Java基础


    线程的异常处理

    setDefaultUncaughtExceptionHandler():设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。Thread.setDefaultUncaughtExceptionHandler(new ThreadUncaughtExceptionHandler())

    线程异常处理实例
    package com.thread.study;
    
    import org.slf4j.Logger;
    
    import static org.slf4j.LoggerFactory.getLogger;
    
    public class ThreadException {
        /** 日志 */
        private static final Logger LOGGER = getLogger(ThreadException.class);
    
        public static void main(String[] args) {
            //异常不处理
            new Thread(() -> {
                int i = 1/0;
            }, "张三").start();
    
            //在线程内异常处理
            new Thread(() -> {
                try {
                    int i = 1/0;
                } catch (Exception e) {
                    LOGGER.error("线程发生了异常,线程内处理", e);
                }
            }, "李四").start();
    
            // 在线程外处理异常
            try {
                new Thread(() -> {
                    int i = 1/0;
                }, "王五").start();
            } catch (Exception e) {
                LOGGER.error("线程发生了异常,线程外处理", e);
            }
    
            // 自定义线程异常处理异常
            Thread thread = new Thread(() -> {
                int i = 1/0;
            },"赵六");
            thread.setUncaughtExceptionHandler(new ThreadUncaughtExceptionHandler());
            thread.start();
        }
    
    }
    
    
    // 自定义线程异常
    class ThreadUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    
        /** 日志 */
        private static final Logger LOGGER = getLogger(ThreadUncaughtExceptionHandler.class);
    
        /**
         * Thread t  发生异常的线程
         * Throwable e  发生的异常
         */
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            LOGGER.error("线程发生了异常,自定义处理。{}", t, e);
        }
    }
    
    打印结果
    Exception in thread "张三" java.lang.ArithmeticException: / by zero
        at com.thread.study.ThreadException.lambda$main$0(ThreadException.java:14)
        at java.lang.Thread.run(Thread.java:745)
    Exception in thread "王五" java.lang.ArithmeticException: / by zero
        at com.thread.study.ThreadException.lambda$main$2(ThreadException.java:29)
        at java.lang.Thread.run(Thread.java:745)
    主线程执行完了
    10:32:02.518 [李四] ERROR com.thread.study.ThreadException - 线程发生了异常,线程内处理
    java.lang.ArithmeticException: / by zero
        at com.thread.study.ThreadException.lambda$main$1(ThreadException.java:20)
        at java.lang.Thread.run(Thread.java:745)
    10:32:02.518 [赵六] ERROR com.thread.study.ThreadUncaughtExceptionHandler - 线程发生了异常,自定义处理。Thread[赵六,5,main]
    java.lang.ArithmeticException: / by zero
        at com.thread.study.ThreadException.lambda$main$3(ThreadException.java:37)
        at java.lang.Thread.run(Thread.java:745)
    
    线程异常处理总结:
    1. 线程中如果发生异常,不处理与在线程外处理效果是一样的。
    2. 线程中如果发生异常,在线程中处理可以捕捉到异常,线程的异常不影响其他线程的执行。
    3. 线程中如果发生异常,使用线程内的try...catch和自定义异常都是可以处理的,并可以获取线程内的异常信息。
    4. 线程内的try...catch和自定义异常处理异常的区别在于,线程内的try...catch只能针对一个线程,自定义异常可以针对一组线程。
    线程通过Future的get方法捕获异常
    package com.thread.study;
    
    import org.slf4j.Logger;
    
    import java.util.concurrent.*;
    
    import static org.slf4j.LoggerFactory.getLogger;
    
    public class ThException {
    
        /** 日志 */
        private static final Logger LOGGER = getLogger(ThreadException.class);
    
        public static void main(String[] args) {
    
            // 线程通过Future的get方法捕获异常
            ExecutorService executorService = Executors.newFixedThreadPool(2);
            Future<Object> future = executorService.submit(new Callable() {
                @Override
                public String call() throws Exception {
                    int i = 1 / 0;
                    return "线程通过Future创建线程";
                }
            });
            try {
                String reStr = (String) future.get();
                System.out.println(reStr);
            } catch (InterruptedException | ExecutionException e) {
                LOGGER.error("线程发生了异常,线程通过Future的get方法捕获异常", e);
            }
            executorService.shutdown();
    
            System.out.println("主线程执行完了");
        }
    }
    // 打印结果
    /*
    11:10:41.841 [main] ERROR com.thread.study.ThreadException - 线程发生了异常,线程通过Future的get方法捕获异常
    java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
        at java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.util.concurrent.FutureTask.get(FutureTask.java:192)
        at com.thread.study.ThException.main(ThException.java:26)
    Caused by: java.lang.ArithmeticException: / by zero
        at com.thread.study.ThException$1.call(ThException.java:21)
        at com.thread.study.ThException$1.call(ThException.java:18)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    主线程执行完了
    */
    
    通过Future的get方法处理总结:

    submit之后可以获得一个线程执行结果的Future对象,而如果子线程中发生了异常,通过future.get()获取返回值时,可以捕获到ExecutionException异常,从而知道子线程中发生的异常信息。

    相关文章

      网友评论

        本文标题:Java基础-线程-线程的异常处理

        本文链接:https://www.haomeiwen.com/subject/stjuzktx.html