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主线程如何等待子线程执行结束(转)
工作中往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线 ...
随机推荐
- websocket协议学习
一 实验代码 client.html websocket_server.go package main import ( "crypto/sha1" "encoding/ ...
- 安装CUDA和cuDNN
GPU和CPU区别 1,CPU主要用于处理通用逻辑,以及各种中断事物 2,GPU主要用于计算密集型程序,可并行运作: NVIDIA 的 GeForce 显示卡系列采用 GPU 特性进行快速计算,渲染电 ...
- 随机森林分类器(Random Forest)
阅读目录 1 什么是随机森林? 2 随机森林的特点 3 随机森林的相关基础知识 4 随机森林的生成 5 袋外错误率(oob error) 6 随机森林工作原理解释的一个简单例子 7 随机森林的Pyth ...
- 浅谈.NET(C#)与Windows用户账户信息的获取
原文:浅谈.NET(C#)与Windows用户账户信息的获取 目录 1. 用户账户名称 - 使用Environment类 2. 用户账户信息 - 使用WindowsIdentity和IdentityR ...
- Redaht7/Oracle Linux7 + ORA11g : ohasd fails to start(Doc ID 1959008.1)
APPLIES TO: Oracle Database - Standard Edition - Version 11.2.0.4 to 12.1.0.1 [Release 11.2 to 12.1] ...
- UWP中的消息提示框(二)
在UWP中的消息提示框(一)中介绍了一些常见的需要用户主动去干涉的一些消息提示框,接下来打算聊聊不需要用户主动去干涉的一些消息提示框.效果就是像双击退出的那种提示框. 先说说比较简单的吧,通过系统To ...
- 快速搭建多线程Windows服务解决方案
一.引言 在软件开发过程中windows服务有的时候非常有用,用于同步数据,发送邮件,宿主WF引擎服务等,但是快速搭建一个好用多线程进行多任务处理的程序往往是一个项目必须考虑的问题.自己在项目中也经常 ...
- Westciv Tools主要为CSS3提供了渐变gradients、盒子阴影box-shadow、变形transform和文字描边四种在线生成效果的工具
Westciv Tools主要为CSS3提供了渐变gradients.盒子阴影box-shadow.变形transform和文字描边四种在线生成效果的工具 1.Westciv Tools 彩蛋爆料直击 ...
- Qt多线程学习-用例子来理解多线程
文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373_3.html) POINT 1:QThread类的实例与 ...
- C#制作浮动图标窗体
先看效果: 这个小图标可以进行随意拖拽,点击还可以产生事件 随便演示一下,效果就是这样的. 下面直接演示如何制作: 新建一个窗体,设置窗体的FormBorderStyle为None(去掉窗体边框): ...