JAVA线程及线程池异常处理

JAVA线程异常处理

  • 在run方法上增加异常处理
new Thread(() -> {
try {
System.err.println(3 / 2);
System.err.println(3 / 0);
} catch (Exception e) {
System.err.println("Catch exception===>" + e.getMessage());
}
}).start();
  • 使用UncaughtExceptionHandler处理未捕获异常
Thread thread = new Thread(() -> {
System.err.println(3 / 2);
System.err.println(3 / 0);
});
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.err.println(Thread.currentThread().getName() + "==>" + e.getMessage());
}
});
thread.start();

可以为所有的Thread设置一个默认的UncaughtExceptionHandler,通过调用Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)方法

public static void main(String[] args) throws InterruptedException {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.err.println("全局线程默认异常处理:" + t.getName() + "\n" + e.getMessage());
}
});
new Thread(() -> {
System.err.println(3 / 0);
}).start();
new Thread(() -> {
System.err.println(args[4]);
}).start();
}

线程池异常处理

ExecutorService->execute方法线程处理

public class ExecuteCaught
{
public static void main(String[] args)
{
ExecutorService exec = Executors.newCachedThreadPool();
Thread thread = new Thread(new Task());
thread.setUncaughtExceptionHandler(new ExceptionHandler());
exec.execute(thread);
exec.shutdown();
}
}
output=====>
1
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at com.exception.Task.run(NoCaughtThread.java:25)
at java.lang.Thread.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

该方式并未捕获异常,正确的处理方法

public class ExecuteCaught
{
public static void main(String[] args)
{
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ThreadPoolTask());
exec.shutdown();
}
}

class ThreadPoolTask implements Runnable
{
@Override
public void run()
{
Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());
System.out.println(3/2);
System.out.println(3/0);
System.out.println(3/1);
}
}

注意

只有通过execute提交的任务,才能将它抛出的异常交给UncaughtExceptionHandler,而通过submit提交的任务,无论是抛出的未检测异常还是已检查异常,都将被认为是任务返回状态的一部分。如果一个由submit提交的任务由于抛出了异常而结束,那么这个异常将被Future.get封装在ExecutionException中重新抛出

public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
exec.submit(() -> {
System.err.println(3 / 0);
});
exec.shutdown();
}
### 未捕获异常

正确方式:

public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
Future<?> future = exec.submit(() -> {
System.err.println(3 / 0);
});
try {
Object o = future.get();
} catch (ExecutionException e) {
System.err.println("捕获异常:" + e.getMessage());
}
exec.shutdown();
}

【知识点】

  1. 如果设置了实例属性uncaughtExceptionHandler(每个线程对象独有),则调用该处理器对未捕获异常进行处理;
  2. 如果没有设置未捕获异常处理器(即1中的uncaughtExceptionHandler),则将线程对象的ThreadGroup当作未捕获异常处理器,在ThreadGroup中获取所以线程对象共享的静态属性defaultUncaughtExceptionHandler来处理未捕获异常(前提是静态的set方法你调用了并且传入处理器实例);
  3. 如果两个set方法都没有调用,那么异常栈信息将被推送到System.err进行处理;

【参考资料】

https://blog.csdn.net/reliveIT/article/details/51167545

猜你喜欢

转载自blog.csdn.net/luoyoub/article/details/81571360