线程 Thread.UncaughtExceptionHandler 异常捕获

Posted baiqiantao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程 Thread.UncaughtExceptionHandler 异常捕获相关的知识,希望对你有一定的参考价值。

setUncaughtExceptionHandler

public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
x
1
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
设置该线程由于未捕获到异常而突然终止时调用的处理程序。
通过明确设置未捕获到的异常处理程序,线程可以完全控制它对未捕获到的异常作出响应的方式。 
如果没有设置这样的处理程序,则该线程的 ThreadGroup 对象将充当其处理程序。

public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()
 
1
public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()
返回该线程由于未捕获到异常而突然终止时调用的处理程序。
如果该线程尚未明确设置未捕获到的异常处理程序,则返回该线程的 ThreadGroup 对象,除非该线程已经终止,在这种情况下,将返回 null。

setDefaultUncaughtExceptionHandler

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

未捕获到的异常处理首先由线程控制,然后由线程的 ThreadGroup 对象控制,最后由未捕获到的默认异常处理程序控制。

如果线程不设置明确的未捕获到的异常处理程序,并且该线程的线程组(包括父线程组)未特别指定其 uncaughtException 方法,则将调用默认处理程序的 uncaughtException 方法

通过设置未捕获到的默认异常处理程序,应用程序可以为那些已经接受系统提供的任何“默认”行为的线程改变未捕获到的异常处理方式(如记录到某一特定设备或文件)。

请注意,未捕获到的默认异常处理程序通常不应顺从该线程的 ThreadGroup 对象,因为这可能导致无限递归。

public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
1
public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
返回线程由于未捕获到异常而突然终止时调用的默认处理程序。如果返回值为 null,则没有默认处理程序。

Thread.UncaughtExceptionHandler

public static interface Thread.UncaughtExceptionHandler
1
public static interface Thread.UncaughtExceptionHandler
所有已知实现类:ThreadGroup

当 Thread 因未捕获的异常而突然终止时,调用处理程序的接口。

当某一线程因未捕获的异常而即将终止时,Java 虚拟机将使用 Thread.getUncaughtExceptionHandler() 查询该线程以获得其 UncaughtExceptionHandler 的线程,并调用处理程序的 uncaughtException 方法,将线程和异常作为参数传递。

如果某一线程没有明确设置其 UncaughtExceptionHandler,则将它的 ThreadGroup 对象作为其 UncaughtExceptionHandler。如果 ThreadGroup 对象对处理异常没有什么特殊要求,那么它可以将调用转发给默认的未捕获异常处理程序。

void uncaughtException(Thread t, Throwable e) 
x
1
void uncaughtException(Thread t, Throwable e) 
当给定线程因给定的未捕获异常而终止时,调用该方法。
Java 虚拟机将忽略该方法抛出的任何异常。

测试案例

public class Test {
	public static void main(String[] args) {
		setDefaultUncaughtExceptionHandler();
		test();
	}

	private static void test() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("子线程异常前");
				System.out.println(1 / 0);
			}
		}).start();
		System.out.println("当前线程异常前");
		System.out.println(1 / 0);
		System.out.println("异常后的代码不能执行了");
	}

	private static void setDefaultUncaughtExceptionHandler() {
		UncaughtExceptionHandler currentHandler = new UncaughtExceptionHandler() {
			@Override
			public void uncaughtException(Thread t, Throwable e) {
				System.out.println("【当前线程的Handler处理异常信息】" + t.toString() + "\n" + e.getMessage());
			}
		};
		UncaughtExceptionHandler defaultHandler = new UncaughtExceptionHandler() {
			@Override
			public void uncaughtException(Thread t, Throwable e) {
				StringWriter writer = new StringWriter();
				PrintWriter printWriter = new PrintWriter(writer);
				printWriter.write("start------------\n");
				e.printStackTrace(printWriter);
				printWriter.write("------------end");
				printWriter.close();
				System.out.println("【默认的Handler处理异常信息】" + writer.getBuffer().toString());
			}
		};
		Thread.currentThread().setUncaughtExceptionHandler(currentHandler);
		Thread.setDefaultUncaughtExceptionHandler(defaultHandler);
	}
}
 
1
public class Test {
2
    public static void main(String[] args) {
3
        setDefaultUncaughtExceptionHandler();
4
        test();
5
    }
6
7
    private static void test() {
8
        new Thread(new Runnable() {
9
            @Override
10
            public void run() {
11
                System.out.println("子线程异常前");
12
                System.out.println(1 / 0);
13
            }
14
        }).start();
15
        System.out.println("当前线程异常前");
16
        System.out.println(1 / 0);
17
        System.out.println("异常后的代码不能执行了");
18
    }
19
20
    private static void setDefaultUncaughtExceptionHandler() {
21
        UncaughtExceptionHandler currentHandler = new UncaughtExceptionHandler() {
22
            @Override
23
            public void uncaughtException(Thread t, Throwable e) {
24
                System.out.println("【当前线程的Handler处理异常信息】" + t.toString() + "\n" + e.getMessage());
25
            }
26
        };
27
        UncaughtExceptionHandler defaultHandler = new UncaughtExceptionHandler() {
28
            @Override
29
            public void uncaughtException(Thread t, Throwable e) {
30
                StringWriter writer = new StringWriter();
31
                PrintWriter printWriter = new PrintWriter(writer);
32
                printWriter.write("start------------\n");
33
                e.printStackTrace(printWriter);
34
                printWriter.write("------------end");
35
                printWriter.close();
36
                System.out.println("【默认的Handler处理异常信息】" + writer.getBuffer().toString());
37
            }
38
        };
39
        Thread.currentThread().setUncaughtExceptionHandler(currentHandler);
40
        Thread.setDefaultUncaughtExceptionHandler(defaultHandler);
41
    }
42
}
运行结果
子线程异常前
当前线程异常前
【当前线程的Handler处理异常信息】Thread[main,5,main]
/ by zero
【默认的Handler处理异常信息】start------------
java.lang.ArithmeticException: / by zero
	at Test$1.run(Test.java:16)
	at java.lang.Thread.run(Thread.java:745)
------------end
1
子线程异常前
2
当前线程异常前
3
【当前线程的Handler处理异常信息】Thread[main,5,main]
4
/ by zero
5
【默认的Handler处理异常信息】start------------
6
java.lang.ArithmeticException: / by zero
7
    at Test$1.run(Test.java:16)
8
    at java.lang.Thread.run(Thread.java:745)
9
------------end
2018-5-31

以上是关于线程 Thread.UncaughtExceptionHandler 异常捕获的主要内容,如果未能解决你的问题,请参考以下文章

如何确定线程池中线程数量

c#线程之前台线程后台线程及使用

Java多线程编程总结

多线程三(线程组和线程池)

主线程怎么给子线程发送消息

聊聊线程模型:用户线程和内核线程