赞
踩
//特定线程设置全局的UncaughtExceptionHandler
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)
//设置全局的UncaughtExceptionHandler
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)
//获取全局的UncaughtExceptionHandler
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
return defaultUncaughtExceptionHandler;
}
//获取特定线程的UncaughtExceptionHandler
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
//仅由JVM调用此方法处理异常
/**
* Dispatch an uncaught exception to the handler. This method is
* intended to be called only by the JVM.
*/
private void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this, e);
}
/** * 使用钩子 处理异常 */ private static void uncaughtException() { Thread.setDefaultUncaughtExceptionHandler((t,e)->{ System.out.println(t); e.printStackTrace(); }); new Thread(()->{ try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(1/0); },"thread_uncaught").start(); } Thread[thread_uncaught,5,main] java.lang.ArithmeticException: / by zero at com.today.roc.go.understand.thread.six.UncaughtExceptionMain.lambda$main$1(UncaughtExceptionMain.java:28) at java.lang.Thread.run(Thread.java:748)
如果当前线程没有UncaughtExceptionHandler,则线程组处理
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
public void uncaughtException(Thread t, Throwable e) { if (parent != null) { //父类不为空,使用父UncaughtExceptionHandler parent.uncaughtException(t, e); } else { //获取全局UncaughtExceptionHandler Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh != null) { ueh.uncaughtException(t, e); } else if (!(e instanceof ThreadDeath)) { //交给System.err处理 System.err.print("Exception in thread \"" + t.getName() + "\" "); e.printStackTrace(System.err); } } }
private static void testNoUncaught(){ ThreadGroup mainGroup = Thread.currentThread().getThreadGroup(); System.out.println(mainGroup); System.out.println(mainGroup.getParent()); System.out.println(mainGroup.getParent().getParent()); new Thread(()->{ try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(1/0); },"uncaught_thread").start(); } java.lang.ThreadGroup[name=main,maxpri=10] java.lang.ThreadGroup[name=system,maxpri=10] null Exception in thread "uncaught_thread" java.lang.ArithmeticException: / by zero at com.today.roc.go.understand.thread.six.UncaughtExceptionMain.lambda$testNoUncaught$2(UncaughtExceptionMain.java:51) at java.lang.Thread.run(Thread.java:748)
当JVM程序停止时,会启动Hook线程,进行事后处理
防止程序重复启动:启动时候创建一个lock文件,添加一个hook当程序停止时删除lock文件,如果文件存在表示程序运行,不能重复启动。
public class HookMain { public static void main(String[] args) { Runtime.getRuntime().addShutdownHook(new Thread( () -> { try { System.out.println("The hook thread 1 is running."); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("The hook thread 1 will exit."); } )); Runtime.getRuntime().addShutdownHook(new Thread( () -> { try { System.out.println("The hook thread 2 is running."); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("The hook thread 2 will exit."); } )); System.out.println("The program will is stopping"); } } The program will is stopping The hook thread 2 is running. The hook thread 1 is running. The hook thread 2 will exit. The hook thread 1 will exit.
/** * Hook实战 */ public static void hook() throws IOException, InterruptedException { Runtime.getRuntime().addShutdownHook(new Thread(()->{ System.out.println(" program has exit "); if (getLookFile().toFile().exists()){ //删除文件 getLookFile().toFile().delete(); } })); checkRunning(); IntStream.range(0,5).forEach(v->{ System.out.println(" the program is running "); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } }); } /** * 检查文件是否存在,如果是第一次启动,创建文件 */ public static void checkRunning() throws IOException { Path path = getLookFile(); if (path.toFile().exists()) { //文件存在,表示已经启动 throw new RuntimeException("the program already running……"); } Files.createFile(path); System.out.println("create file success"); } public static Path getLookFile() { return Paths.get(LOCK_PATH, LOCK_FILE); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。