Java Thread线程异常监控

一、场景描述:单线程程序可以用try...catch捕获程序的异常,而在多线程程序的时候是无法使用try...catch捕获。

示例1:多线程发生异常,无法使用try...catch捕获问题

public class NoCaughtThread implements Runnable{ @Override public void run() { System.out.println(3 / 2); System.out.println(3 / 0); System.out.println(3 / 1); } public static void main(String[] args) { try { Thread thread = new Thread(new NoCaughtThread()); thread.start(); } catch (Exception e) { System.out.println("==Exception: " + e.getMessage()); } } }

运行结果:

1
Exception in thread "Thread-0" Java.lang.ArithmeticException: / by zero
at threadtest.NoCaughtThread.run(NoCaughtThread.java:7)
at java.lang.Thread.run(Thread.java:724)

显然这并非程序设定异常捕获,此时try...catch无法捕获线程的异常。此时,如果线程因为异常而终止执行将无法检测到异常。究其原因Thread类run()方法是不抛出任何检查型异常的,而自身却可能因为一个异常而被中止。

二、解决方式大致有两种:① 在run()中设置对应的异常处理,主动方法来解决未检测异常;② Thread类API中提供Interface接口UncaughtExceptionHandler,该接口包含uncaughtException方法,它能检测出某个未捕获的异常而终结的情况;

示例2:主动的检测异常

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class InitiativeCaught { public static void main(String[] args) { InitialtiveThread initialtiveThread = new InitialtiveThread() ; ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(initialtiveThread); exec.shutdown(); } } class InitialtiveThread implements Runnable { @Override public void run() { Throwable thrown = null; try { System.out.println(3 / 2); System.out.println(3 / 0); System.out.println(3 / 1); } catch (Throwable e) { thrown = e; } finally { threadDeal(this, thrown); } } public void threadDeal(Runnable r, Throwable t) { System.out.println("==Exception: " + t.getMessage()); } }

运行结果:

1
==Exception: / by zero

此时是主动捕获异常并做处理,得到想要的结果。

示例3:Thread类API中提供UncaughtExceptionHandler接口捕获异常,要求检测线程异常,发生异常设置为重复调用三次之后结束线程。

import java.lang.Thread.UncaughtExceptionHandler; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadMonitor implements Runnable { private int data; // 可设置通过构造传参 private int control = 0; private static final int MAX = 3; // 设置重试次数 public ThreadMonitor(int i) { this.data = i; } public ThreadMonitor() { // TODO Auto-generated constructor stub } @Override public void run() { Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread arg0, Throwable e) { // TODO Auto-generated method stub System.out.println("==Exception: " + e.getMessage()); String message = e.getMessage(); if( control==MAX ){ return ; }else if( "ok".equals(message) ){ return ; }else if ( "error".equals(message) ) { new Thread() { public void run() { try { System.out.println("开始睡眠。"); Thread.sleep(1 * 1000); control++ ; System.out.println("睡眠结束,control: "+ control); myTask(data) ; } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); }else{ return ; } } }); myTask(data) ; } @SuppressWarnings("finally") public void myTask(int data){ boolean flag = true ; try { System.out.println(4 / data); } catch (Exception e) { flag = false ; } finally { if( flag ){ throw new RuntimeException("ok"); }else{ throw new RuntimeException("error"); } } } public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); ThreadMonitor threadMonitor = new ThreadMonitor(0); exec.execute(threadMonitor); exec.shutdown(); } }

运行结果:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/782cda6552ad656c713edf82aa0d8f46.html