Java的Hook线程及捕获线程执行异常
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.util.Set; import java.util.concurrent.TimeUnit; public class Test { public static void main(String[] args){ // CaptureThreadException.test(); // EmptyException.test(); // ThreadHook.test(); PreventDuplicated.test(); } } /* 7.1 获取线程运行时异常 public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) :为某个线程指定UncaughtExceptionHandler public UncaughtExceptionHandler getUncaughtExceptionHandler(); :获取某个线程的UncaughtExceptionHandler public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) :设置全局的UncaughtExceptionHandler public static void setDefaultUncaughtExceptionHandler(UncaughtException eh) :获取全局的UncaughtExceptionHandler 函数接口,该回调接口会被Thread中的dispatchUncaughtExcept方法调用,当线程在运行 的过程中出现了异常时,JVM会调用dispatchUncaughtExcept方法,该方法将对应的线程实 例以及异常信息传递给回调接口: public interface UncaughtExceptionHandler{ void uncaughtException(Thread t, Throwable e); } private void dispatchUncaughtExcept(Throwable e){ getUncaughtExceptionHandler().uncaughtException(this.e); } 闲谈: 在平时的工作中,这种设计方式是比较常见的,尤其是那种异步执行方法,不如Google的 guava toolkit就提供了EventBus,在EventBus中事件源和实践的subscriber两者 借助于EventBus实现了完全的解耦合,但是在subscriber执行任务时有可能会出现异常 情况,EventBus同样也是借助一个ExceptionHandler进行回调处理的。 */ class CaptureThreadException{ public static void test() { Thread.setDefaultUncaughtExceptionHandler((t,e)->{ System.out.println(t.getName()+" occur exception"); e.printStackTrace(); }); final Thread t = new Thread(()->{ try{ TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { } System.out.println(1/0); },"Test-Thread"); t.start(); } } /* 7.1.3 UncaughtExceptionHandler源码分析 未注入UncaughtExceptionHandler回调接口的情况下,就从ThreadGroup中获取: 1.该ThreadGroup如果有父ThreadGroup,则直接使用父Group的UncaughtException 2.如果设置了全局默认的UncaughtExceptionHandler,则调用UncaughtException 3.既没有父,又没有全局的,则直接将异常的堆栈信息定向到System.err中 案例分析: 由于没有指定,所以寻找过程为: 线程出现异常=>Main Group=>System Group=>System.err */ class EmptyException{ public static void test() { ThreadGroup main = Thread.currentThread().getThreadGroup(); System.out.println(main.getName()); System.out.println(main.getParent()); System.out.println(main.getParent().getParent()); final Thread thread = new Thread(()->{ try{ TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(1/0); },"Test-Thread"); thread.start(); } } /* 7.2.1 Hook线程介绍 Jvm进程的退出是由于JVM进程没有活跃的非守护线程,或者系统中断了信号。向JVM程序 注入多个Hook线程,在JVM进程退出的时候,Hook线程会启动执行,通过Runtime可以为 JVM注入多个Hook线程。 */ class ThreadHook{ public static void test() { Runtime.getRuntime().addShutdownHook(new Thread(){ public void run(){ 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(){ public void run(){ 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."); } }); } } /* 7.2.2 Hook线程实战 需求: 在我们开发中经常会遇到Hook线程,比如为了防止某个程序被重复启动,在进行启动时 会创建一个lock文件,进程收到中断信号的时候会删除这个lock文件,我们在mysql服 务器、zookeeper、kafka等系统中都能看到lock文件的存在,本节,将利用hook线程 的特点,模拟一个防止重复启动的线程。 */ class PreventDuplicated { private final static String LOCK_PATH = "C:\\Users\\Administrator\\Desktop\\JavaAPI"; private final static String LOCK_FILE = ".lock"; private final static String PERMISSIONS = "rw-------"; private static Path getLockFile(){ return Paths.get(LOCK_PATH,LOCK_FILE); } private static void checkRunning(){ Path path = getLockFile(); if(path.toFile().exists()){ throw new RuntimeException("The program already running..."); } /* 很尴尬一点,这个地方貌似是针对Linux的写法,我这个地方出现了问题, 暂时先将这个问题放一下吧。。。 */ Set<PosixFilePermission> perms = PosixFilePermissions.fromString(PERMISSIONS); try { Files.createFile(path,PosixFilePermissions.asFileAttribute(perms)); } catch (IOException e) { e.printStackTrace(); } } public static void test(){ Runtime.getRuntime().addShutdownHook(new Thread(){ @Override public void run() { System.out.println("The program received kill SIGNAL."); getLockFile().toFile().delete(); } }); checkRunning(); while (true) { try{ TimeUnit.MILLISECONDS.sleep(1); System.out.println("program is running..."); } catch (InterruptedException e) { e.printStackTrace(); } } } } /* 7.2.3 Hook线程应用场景及注意事项 1.Hook线程只有在收到退出信号的时候会被执行,如果kill使用了-9,那么 Hook线程不会执行,因此lock文件也不会被清理 2.Hook线程中也可以执行一些资源的释放工作,如关闭文件句柄、socket链接 、数据库connection等 */
《Java高并发编程详解》笔记
Java的Hook线程及捕获线程执行异常的更多相关文章
- C#通过接口与线程通信(捕获线程状态)介绍
C#通过接口与线程通信(捕获线程状态)介绍 摘要:本文介绍C#通过接口与线程通信(捕获线程状态),并提供简单的示例代码供参考. 提示:本文所提到的线程状态变化,并不是指线程启动.暂停.停止,而是说线程 ...
- java并发编程(四) 线程池 & 任务执行、终止源码分析
参考文档 线程池任务执行全过程:https://blog.csdn.net/wojiaolinaaa/article/details/51345789 线程池中断:https://www.cnblog ...
- Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程
Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程 一.捕获异常并重新启用线程 public class Testun { public static voi ...
- 死磕 java线程系列之线程池深入解析——普通任务执行流程
(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 前面我们一起学习了Java中 ...
- java主线程等待所有子线程执行完毕在执行(常见面试题)
java主线程等待所有子线程执行完毕在执行(常见面试题) java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个 ...
- Java中主线程如何捕获子线程抛出的异常
首先明确线程代码的边界.其实很简单,Runnable接口的run方法所界定的边界就可以看作是线程代码的边界.Runnable接口中run方法原型如下: public void run(); 而所有的具 ...
- 死磕 java线程系列之线程池深入解析——未来任务执行流程
(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 前面我们一起学习了线程池中普 ...
- 【Java多线程系列四】控制线程执行顺序
假设有线程1/线程2/线程3,线程3必须在线程1/线程2执行完成之后开始执行,有两种方式可实现 Thread类的join方法:使宿主线程阻塞指定时间或者直到寄生线程执行完毕 CountDownLatc ...
- Java主线程如何等待子线程执行结束(转)
工作中往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线 ...
随机推荐
- SpringMvc 资料
web.xml解释 http://www.cnblogs.com/superjt/p/3309255.html url-pattern解释 http://www.cnblogs.com/zhangpe ...
- Android零基础入门第18节:EditText的属性和使用方法
原文:Android零基础入门第18节:EditText的属性和使用方法 EditText与TextView非常相似,它甚至与TextView 共用了绝大部分XML属性和方法.EditText与Tex ...
- lvcreate命令
lvcreate Command Examples on Linux : 1. The following command creates a logical volume 15 gigabytes ...
- 使用Boost的DLL库管理动态链接库(类似于Qt中的QLibrary)
Boost 1.61新增了一个DLL库,跟Qt中的QLibrary类似,提供了跨平台的动态库链接库加载.调用等功能.http://www.boost.org/users/history/version ...
- VCL的通用属性,方法和事件 good
Action 一些组件标识与组件相连接的活动对象Align 一些组件确定组件在父类组件区内的对齐方式Anchors 大部分组件说明与组件连接的窗体的位置点AutoSize 一些组件说明组件是否可根据内 ...
- Delphi 屏幕抓图技术的实现
摘 要:本文以Delphi7.0作为开发平台,给出了网络监控软件中的两种屏幕抓图技术的设计方法和步骤.介绍了教师在计算机机房内教学时,如何监控学生计算机显示器上的画面,以保证教学的质量和效果. 引言 ...
- 从Qt5开始只剩下setCodecForLocale这一个了,只是影响Qt对toLocal8Bit相关函数的编码方式(在源码里写非英文,官方推荐“\xE4\xBD...”这种)good
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecFo ...
- c# 文本超长截断
根据控件大小进行截断 private void SetStringTruncat(Static.LabelEx lbl) { string oldStr = lbl.Text; if (string. ...
- 剖析Qt的事件机制原理(源代码级别)
在用Qt写Gui程序的时候,在main函数里面最后依据都是app.exec();很多书上对这句的解释是,使Qt程序进入消息循环.下面我们就到exec()函数内部,来看一下他的实现原理.Let's go ...
- <第三方>TGRefreshO按照QQ的刷新方式下拉刷新
一 .使用方法: 刷新机制,类似QQ一样的刷新机制,弹簧.橡皮筋下拉刷新控件,类似QQ下拉刷新效果,同时支持其他样式: 首先写上这一句(必须的) #import <TGRefresh ...