面试官: 说说看什么是 Hook (钩子) 线程以及应用场景?

一、Hook 线程介绍

通常情况下,我们可以向应用程序注入一个或多个 Hook (钩子) 线程,这样,在程序即将退出的时候,也就是 JVM 程序即将退出的时候,Hook 线程就会被启动执行

先看一段示例代码:

:为应用程序注入一个钩子(Hook)线程,线程中,打印了相关日志,包括正在运行以及退出的日志;
:再次注入一个同样逻辑的钩子(Hook)线程;
:主线程执行结束,打印日志;

运行这段代码,来验证一下:


从打印日志看到,当主线程执行结束,也就是 JVM 进程即将退出的时候,注入的两个 Hook 线程都被启动并打印相关日志。

二、Hook 线程的应用场景&注意事项

2.1 应用场景

上面我们已经知道了, Hook 线程能够在 JVM 程序退出的时候被启动且执行,那么,我们能够通过这种特性,做点什么呢?

罗列一些常见应用场景:

防止程序重复执行,具体实现可以在程序启动时,校验是否已经生成 lock 文件,如果已经生成,则退出程序,如果未生成,则生成 lock 文件,程序正常执行,最后再注入 Hook 线程,这样在 JVM 退出的时候,线程中再将 lock 文件删除掉;

PS: 这种防止程序重复执行的策略,也被应用于 Mysql 服务器,zookeeper, kafka 等系统中。

Hook 线程中也可以执行一些资源释放的操作,比如关闭数据库连接,Socket 连接等。

2.2 注意事项

  • Hook 线程只有在正确接收到退出信号时,才能被正确执行,如果你是通过 kill -9这种方式,强制杀死的进程,那么抱歉,进程是不会去执行 Hook 线程的,为什么呢?你想啊,它自己都被强制干掉了,哪里还管的上别人呢?
  • 请不要在 Hook 线程中执行一些耗时的操作,这样会导致程序长时间不能退出。

三、Hook 线程防应用重启实战

针对上面防应用重启的场景,利用 Hook 线程,我们来实战一下,贴上代码:

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
 * @author 小泽java
 * @date 2019/4/15
 * @time 下午3: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();
 }
}
</pre>

运行程序,控制台输出如下:

程序一直运行中,再来看下 .lock 文件是否生成:

文件生成成功,接下来,我们再次运行程序,看看是否能够重复启动:

可以看到,无法重复运行程序,且抛出了 The program already running. 的运行时异常。接下来,通过 kill pid 或者 kill -l pid 命令来结束进程:

程序在即将退出的时候,启动了 Hook 线程,在看下 .lock 文件是否已被删除:

到此,Hook 线程代码实战部分结束了。

原文地址:https://blog.51cto.com/14257804/2379579

时间: 2024-12-21 07:53:06

面试官: 说说看什么是 Hook (钩子) 线程以及应用场景?的相关文章

面试官: 什么是 Hook (钩子) 线程以及应用场景?

一.Hook 线程介绍 通常情况下,我们可以向应用程序注入一个或多个 Hook (钩子) 线程,这样,在程序即将退出的时候,也就是 JVM 程序即将退出的时候,Hook 线程就会被启动执行. 先看一段示例代码: ①:为应用程序注入一个钩子(Hook)线程,线程中,打印了相关日志,包括正在运行以及退出的日志:②:再次注入一个同样逻辑的钩子(Hook)线程:③:主线程执行结束,打印日志: 运行这段代码,来验证一下: 从打印日志看到,当主线程执行结束,也就是 JVM 进程即将退出的时候,注入的两个 H

Redis Cluster 原理详解,应付面试官就看这一篇!

Redis 缓存作为使用最多的缓存工具被各大厂商争相使用.通常我们会使用单体的 Redis 应用作为缓存服务,为了保证其高可用还会使用主从模式(Master-Slave),又或者是读写分离的设计.但是当缓存数据量增加以后,无法用单体服务器承载缓存服务时,就需要对缓存服务进行扩展.将需要缓存的数据切分成不同的分区,将数据分区放到不同的服务器中,用分布式的缓存来承载高并发的缓存访问.恰好 Redis Cluster 方案刚好支持这部分功能. 今天就来一起看看 Redis Cluster 的核心原理和

面试官: 谈谈什么是守护线程以及作用 ?

文章首发自微信公众号: 小哈学Java 个人网站: https://www.exception.site/java-concurrency/java-concurrency-daemon-thread 目录 一.什么是守护线程 二.守护线程的作用及应用场景 三.总结 一.什么是守护线程 守护线程相对于正常线程来说,是比较特殊的一类线程,那么它特殊在哪里呢?别急,在了解它之前,我们需要知道一个问题,那就是: JVM 程序在什么情况下能够正常退出? The Java Virtual Machine

面试官的七种武器:Java篇

起源 自己经历过的面试也不少了,互联网的.外企的,都有.总结一下这些面试的经验,发现面试官问的问题其实不外乎几个大类,玩不出太多新鲜玩意的.细细想来,面试官拥有以下七种武器.恰似古龙先生笔下的武侠世界中的七种武器.下面我为各位一一道来. (欢迎转载.转载请注明出处:http://www.cnblogs.com/hzg1981/) 长生剑=语言基础 长生剑是七种武器之首,同理,编程语言的考察也是技术面试中最基本的.这条不满足的就直接Pass了.以Java为例,语言的考察大致可以分为三个层次: 初级

面试必看|如何避免减分项雷区,看面试官筛选简历八大关键点

金三银四跳槽季已经结束了,铜五铁六的情况也不容乐观.我和同事们看了很多简历,也邀请了很多人参加面试,最终通过的寥寥无几. 想必很多面试者都很郁闷,为什么投了这么多简历,最后都杳无音讯.是简历的问题吗? 今天就来聊点扎心的事儿,面试官是怎么在短时间内筛选简历的.哪些是明显的减分项.请大家扬长避短,把简历尽量写得漂亮一些. 本文观点仅代表参与讨论的几位 BAT 同学. 教育背景不够好 首先,大公司筛选简历确实是"英雄不问出处"的. 不管你来自高大上的常春藤还是国内不显眼的二本院校,不管你是

去百度面试,想知道面试官问哪些问题,看这篇文章

https://mp.weixin.qq.com/s?__biz=MzI0NjM3NjI1NQ==&mid=2247487861&idx=1&sn=34316976cdb0aa2e4df3aa6f1f5cc31d&chksm=e9416325de36ea33200d9944fff37381de11c8d4dc8aeb0cc4b83c6201e56b8ee2bc8c2798cc&mpshare=1&scene=1&srcid=1102ElP5k7MBT

(转)史上最全 40 道 Dubbo 面试题及答案,看完碾压面试官!

背景:因为自己的简历写了dubbo,面试时候经常被问到.实际自己对dubbo的认识只停留在使用阶段,所以有必要好好补充下基础的理论知识. https://zhuanlan.zhihu.com/p/45846108 想往高处走,怎么能不懂 Dubbo? Dubbo是国内最出名的分布式服务框架,也是 Java 程序员必备的必会的框架之一.Dubbo 更是中高级面试过程中经常会问的技术,无论你是否用过,你都必须熟悉. 下面我为大家准备了一些 Dubbo 常见的的面试题,一些是我经常问别人的,一些是我过

改了 3 年的技术简历,终于能让面试官看顺眼了

阅读本文大概需要 7 分钟. 作者:黄小斜 怎样制作一份优秀的技术简历.相信很多同学都对此有疑问,实际上,制作简历这件事,说难也不难,说简单也不简单. 简单,是因为你只需要它需要的内容其实并不多,只需要你花一下午的时间,找一份简历模板,然后把内容写满即可. 难,是因为你要把你毕生所学提炼成一纸简历,并且要投其所好,让面试官看到他想要看到的,同时也是你自己最为擅长的. 要意识到这一点,其实很不容易.很多朋友也拿过自己的简历给我看,质量参差不齐,但是一般愿意把简历拿给我看的朋友,他们是知道自己简历存

面试官再问你 HashMap 底层原理,就把这篇文章甩给他看

前言 HashMap 源码和底层原理在现在面试中是必问的.因此,我们非常有必要搞清楚它的底层实现和思想,才能在面试中对答如流,跟面试官大战三百回合.文章较长,介绍了很多原理性的问题,希望对你有所帮助~ 目录 本篇文章主要包括以下内容: HashMap 的存储结构 常用变量说明,如加载因子等 HashMap 的四个构造函数 tableSizeFor()方法及作用 put()方法详解 hash()方法,以及避免哈希碰撞的原理 resize()扩容机制及原理 get()方法 为什么HashMap链表会