1.如何获得线程的异常
public class ExitCapture { public static void main(String[] args) { //java中的Runtime可以调用shell脚本和.exe文件 //在程序运行结束时得到一个钩子,当程序抛出异常时并不会立即结束。 Runtime.getRuntime().addShutdownHook(new Thread(()->{ System.out.println("The application will be exit."); notifyAndrelease(); }));//关闭时得到一个钩子 int i=0; while(true){ try { Thread.sleep(1000); System.out.println("I am working."); } catch (InterruptedException e) { e.printStackTrace(); } i++; if(i>20) throw new RuntimeException("error"); } } private static void notifyAndrelease(){ System.out.println("notify to the admain"); try{ Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("will release resource"); try{ Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("will release down!!"); } }利用钩子程序可以防止程序出现异常时可以利用钩子程序释放资源(数据库连接、网络连接),这样可以避免当程序异常终止时由操作系统释放资源造成系统资源紧张。
线程中的run()方法是不允许抛出异常的,只能在线程中捕获异常并将异常打印到控制台/log,但是无法将异常告诉前端。
类似于以下程序:
public class ThreadException { private final static int A=10; private final static int B=0; public static void main(String[] args) { Thread t=new Thread(()->{ try { Thread.sleep(5000); int result=A/B; System.out.println(result); } catch (InterruptedException e) { e.printStackTrace(); } }); t.start(); } }运行结果: 只能打印到控制台,但是不能将线程抛出的异常获取(catch)到
Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero at com.learn.thread.ThreadException.lambda$main$0(ThreadException.java:13) at java.lang.Thread.run(Thread.java:748)对原程序进行改进:
public class ThreadException { private final static int A=10; private final static int B=0; public static void main(String[] args) { Thread t=new Thread(()->{ try { Thread.sleep(5000); int result=A/B; System.out.println(result); } catch (InterruptedException e) { e.printStackTrace(); } }); //利用setUncaughtExceptionHandler方法获取线程未捕获的异常,并将异常打印出来。 t.setUncaughtExceptionHandler((thread,e)->{ System.out.println(e); System.out.println(thread); }); t.start(); } }运行结果:
java.lang.ArithmeticException: / by zero //打印异常 Thread[Thread-0,5,main] // Thread-0表示线程名称 5代表优先级 main代表其所在的线程组利用getStackTrace()方法打印函数的调用关系和调用位置
getStackTrace()方法 运行结果: