文章首发自我的微信号: 小哈学Javajava
我的网站地址: https://www.exception.site/java-concurrency/java-concurrency-hook-threadgit
1、Hook 线程介绍github
2、Hook 线程的应用场景&注意事项面试
3、Hook 线程防应用重启实战sql
4、GitHub 源码地址数据库
5、总结服务器
一般状况下,咱们能够向应用程序注入一个或多个 Hook (钩子) 线程,这样,在程序即将退出的时候,也就是 JVM 程序即将退出的时候,Hook 线程就会被启动执行。微信
先看一段示例代码:学习
运行这段代码,来验证一下:网站
从打印日志看到,当主线程执行结束,也就是 JVM 进程即将退出的时候,注入的两个 Hook 线程都被启动并打印相关日志。
上面咱们已经知道了, Hook 线程可以在 JVM 程序退出的时候被启动且执行,那么,咱们可以经过这种特性,作点什么呢?
罗列一些常见应用场景:
PS: 这种防止程序重复执行的策略,也被应用于 Mysql 服务器,zookeeper, kafka 等系统中。
kill -9
这种方式,强制杀死的进程,那么抱歉,进程是不会去执行 Hook 线程的,为何呢?你想啊,它本身都被强制干掉了,哪里还管的上别人呢?针对上面防应用重启的场景,利用 Hook 线程,咱们来实战一下,贴上代码:
import java.io.File; import java.io.IOException; import java.util.concurrent.TimeUnit; /** * @author 犬小哈(微信号: 小哈学Java) * @date 2019/4/10 * @time 下午9:56 * @discription **/ public class PreventDuplicated { /** .lock 文件存放路径 */ private static final String LOCK_FILE_PATH = "./"; /** .lock 文件名称 */ private static final String LOCK_FILE_NAME = ".lock"; public static void main(String[] args) { // 校验 .lock 文件是否已经存在 checkLockFile(); // 注入 Hook 线程 addShutdownHook(); // 模拟程序一直运行 for (;;) { try { TimeUnit.SECONDS.sleep(1); System.out.println("The program is running ..."); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 注入 Hook 线程 */ private static void addShutdownHook() { Runtime.getRuntime().addShutdownHook(new Thread(() -> { // 接受到了退出信号 System.out.println("The program received kill signal."); // 删除 .lock 文件 deleteLockFile(); })); } /** * 校验 .lock 文件是否已经存在 */ private static void checkLockFile() { if (isLockFileExisted()) { // .lock 文件已存在, 抛出异常, 退出程序 throw new RuntimeException("The program already running."); } // 不存在,则建立 .lock 文件 createLockFile(); } /** * 建立 .lock 文件 */ private static void createLockFile() { File file = new File(LOCK_FILE_PATH + LOCK_FILE_NAME); try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } /** * .lock 文件 是否存在 * @return */ private static boolean isLockFileExisted() { File file = new File(LOCK_FILE_PATH + LOCK_FILE_NAME); return file.exists(); } /** * 删除 .lock 文件 */ private static void deleteLockFile() { File file = new File(LOCK_FILE_PATH + LOCK_FILE_NAME); file.delete(); } }
运行程序,控制台输出以下:
程序一直运行中,再来看下 .lock
文件是否生成:
文件生成成功,接下来,咱们再次运行程序,看看是否可以重复启动:
能够看到,没法重复运行程序,且抛出了 The program already running.
的运行时异常。接下来,经过 kill pid
或者 kill -l pid
命令来结束进程:
程序在即将退出的时候,启动了 Hook 线程,在看下 .lock
文件是否已被删除:
到此,Hook 线程代码实战部分结束了。
https://github.com/weiwosuoai/java-concurrent-tutorial
本文中,咱们学习了什么是 Hook (钩子) 线程,相关应用场景以及注意事项。祝你学习愉快 !
获取方式: 关注微信公众号: 小哈学Java, 后台回复"666",既可免费无套路获取资源连接,下面是目录以及部分截图: