线程的异常处理
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)
线程异常处理总结:
- 线程中如果发生异常,不处理与在线程外处理效果是一样的。
- 线程中如果发生异常,在线程中处理可以捕捉到异常,线程的异常不影响其他线程的执行。
- 线程中如果发生异常,使用线程内的try...catch和自定义异常都是可以处理的,并可以获取线程内的异常信息。
- 线程内的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异常,从而知道子线程中发生的异常信息。
网友评论