美文网首页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多线程异常处理

    线程异常处理 Java中每个线程的异常处理是相互独立的,一个线程产生的异常不会影响其他线程的正常运行。因此,也不能...

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

    Java工程师知识树[https://www.jianshu.com/p/db77d19a25f6] / Ja...

  • Java后端知识体系

    基础重点(必须扎实) Java语言 语言基础 《Java核心技术》基础语法面向对象常用API异常处理集合IO多线程...

  • 多线程之线程属性

    线程属性 线程优先级 守护线程 线程组 处理未捕获异常的处理器 1. 线程优先级 在java中,每个线程都有一个...

  • 并发3 下

    线程属性:包括线程优先级,守护线程,线程组以及处理未捕获异常的处理器。 线程优先级 在java程序设计语言中,每一...

  • 自己的事情自己做,线程异常处理

    之前使用线程执行任务的时候,总是忽略了线程异常的处理,直到最近看书 线程出现异常测试类 任务类:Task.java...

  • Java线程系列——线程异常处理

    1.子线程中处理异常的弊端 多线程抛出的异常,容易在主线程大量的日志打印中丢失,给日志排查带来了一定的困难。如下面...

  • Java 线程异常处理

    如果我们调用一个线程处理任务,但是当线程发生异常的时候我们调用线程的地方无法捕捉到异常。用例子验证:我在main中...

  • 2018-07-05学习

    1.认清自己 有一定的Java基础,但是对面向对象概念、集合的概念、io、多线程、并发、处理异常、Java网络编程...

  • Java面试题

    Java面试 Java、框架、JVM Java 基础、容器、多线程、反射、对象拷贝、Java web模块、异常模块...

网友评论

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

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