0
点赞
收藏
分享

微信扫一扫

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

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异常,从而知道子线程中发生的异常信息。

举报

相关推荐

0 条评论