文章目录

  • ThreadGroup介绍
    • ThreadGroup的基本操作
    • ThreadGroup的其他方法
  • 钩子线程
    • 用hook线程模拟防重复启动程序

ThreadGroup介绍

ThreadGroup并不能提供对线程的管理,ThreadGroup的主要功能是对线程进行组织,下面将详细介绍ThreadGroup的主要方法。

ThreadGroup的基本操作

activeCount()用于获取group中活跃的线程,这只是个估计值,并不能百分之百地保证数字一定正确,原因前面已经分析过,该方法会递归获取其他子group中的活跃线程。

activeGroupCount()用于获取group中活跃的子group,这也是一个近似估值,该方法也会递归获取所有的子group。

getMaxPriority()用于获取group的优先级,默认情况下,Group的优先级为10,在该group中,所有线程的优先级都不能大于group的优先级

getName()用于获取group的名字。

getParent()用于获取group的父group,如果父group不存在,则会返回null,比如system group的父group就为null。 list()该方法没有返回值,执行该方法会将group中所有的活跃线程信息全部输出到控制台,也就是System.out。

parentOf(ThreadGroup g)会判断当前group是不是给定group的父group,另外如果给定的group就是自己本身,那么该方法也会返回true。

setMaxPriority(int pri)会指定group的最大优先级,最大优先级不能超过父group的最大优先级,执行该方法不仅会改变当前group的最大优先级,还会改变所有子group的最大优先级。 下面我们给出一个简单的例子来测试一下上面的几个方法。

package com.wangwenjun.concurrent.chapter06;import java.util.concurrent.TimeUnit;public class ThreadGroupBasic
{public static void main(String[] args) throws InterruptedException{/** Create a thread group and thread.*/ThreadGroup group = new ThreadGroup("group1");Thread thread = new Thread(group, () ->{while (true){try{TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e){e.printStackTrace();}}}, "thread");thread.setDaemon(true);thread.start();//make sure the thread is startedTimeUnit.MILLISECONDS.sleep(1);ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();System.out.println("activeCount=" + mainGroup.activeCount());System.out.println("activeGroupCount=" + mainGroup.activeGroupCount());System.out.println("getMaxPriority=" + mainGroup.getMaxPriority());System.out.println("getName=" + mainGroup.getName());System.out.println("getParent=" + mainGroup.getParent());mainGroup.list();System.out.println("--------------------------");System.out.println("parentOf="+mainGroup.parentOf(group));System.out.println("parentOf="+mainGroup.parentOf(mainGroup));}}

这里需要特别说明的是setMaxPriority,我们通过分析源码得出结论,线程的最大优先级,不能高于所在线程组的最大优先级,但是如果我们把代码写成下面这样会怎么样呢?

ThreadGroup的其他方法

ThreadGroup的interrupt

interrupt一个thread group会导致该group中所有的active线程都被interrupt,也就是说该group中每一个线程的interrupt标识都被设置了

ThreadGroup的destroy
destroy用于销毁ThreadGroup,该方法只是针对一个没有任何active线程的group进行一次destroy标记,调用该方法的直接结果是在父group中将自己移除:

钩子线程

JVM进程的退出是由于JVM进程中没有活跃的非守护线程,或者收到了系统中断信号,向JVM程序注入一个Hook线程,在JVM进程退出的时候,Hook线程会启动执行,通过Runtime可以为JVM注入多个Hook线程,下面就通过一个简单的例子来看一下如何向Java程序注入Hook线程。

ThreadHook.java package com.wangwenjun.concurrent.chapter07;import java.util.concurrent.TimeUnit;public class ThreadHook
{public static void main(String[] args){//为应用程序注入钩子线程Runtime.getRuntime().addShutdownHook(new Thread(){@Overridepublic 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(){@Overridepublic 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.");}});System.out.println("The program will is stopping.");}
}

在上面代码中,给Java程序注入了两个Hook线程,在main线程中结束,也就是JVM中没有了活动的非守护线程,JVM进程即将退出时,两个Hook线程会被启动并且运行,输出结果如下:

在我们的开发中经常会遇到Hook线程,比如为了防止某个程序被重复启动,在进程启动时会创建一个lock文件,进程收到中断信号的时候会删除这个lock文件,我们在mysql服务器、zookeeper、kafka等系统中都能看到lock文件的存在,本节中,将利用hook线程的特点,模拟一个防止重复启动的程序,

用hook线程模拟防重复启动程序

package com.wangwenjun.concurrent.chapter07;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 PreventDuplicated
{private final static String LOCK_PATH = "/home/wangwenjun/locks/";private final static String LOCK_FILE = ".lock";private final static String PERMISSIONS = "rw-------";public static void main(String[] args) throws IOException
{//① 注入Hook线程,在程序退出时删除lock文件Runtime.getRuntime().addShutdownHook(new Thread(() ->{System.out.println("The program received kill SIGNAL.");getLockFile().toFile().delete();}));//② 检查是否存在.lock文件checkRunning();//③ 简单模拟当前程序正在运行for (; ; ){try{TimeUnit.MILLISECONDS.sleep(1);System.out.println("program is running.");} catch (InterruptedException e){e.printStackTrace();}}}private static void checkRunning() throws IOException{Path path = getLockFile();if (path.toFile().exists())throw new RuntimeException("The program already running.");Set<PosixFilePermission> perms = PosixFilePermissions.fromString(PERMISS-IONS);Files.createFile(path, PosixFilePermissions.asFileAttribute(perms));}private static Path getLockFile(){return Paths.get(LOCK_PATH, LOCK_FILE);}
}

运行上面的程序,会发现在/home/wangwenjun/locks目录下多了一个.lock文件,程序运行则会创建.lock文件以防止重复启动
执行kill pid或者kill-1 pid命令之后,JVM进程会收到中断信号,并且启动hook线程删除.lock文件。

Hook线程是一个非常好的机制,可以帮助程序获得进程中断信号,有机会在进程退出之前做一些资源释放的动作,或者做一些告警通知。切记如果强制杀死进程,那么进程将不会收到任何中断信号。

注:笔记来自书籍《java高并发编程详解》

【java读书笔记】ThreadGroup和钩子线程的使用相关推荐

  1. Java读书笔记(4)-多线程(二)

    Java读书笔记(4)-多线程(二) 2016-1-2 线程通信 传统的线程通信 Object类提供了wait(),notify()和notifyAll三个方法 适用情况:synchronized修饰 ...

  2. think in java 读书笔记 2 —— 套接字

    目录 think in java 读书笔记 1 --移位 think in java 读书笔记 2 -- 套接字 think in java 读书笔记 3 -- 数据报 概要 1. 套接字基本知识 2 ...

  3. Java读书笔记(8)-单例模式

    Java读书笔记(8)-单例模式 今天在阅读<Effective Java 2>第3条时,获知一种使用枚举enum实现单例模式的新方法,然而书上并没有就此展开深入说明,于是上网查阅了一些资 ...

  4. head first java读书笔记

    head first java读书笔记 1. 基本信息 页数:689 阅读起止日期:20170104-20170215 2. 标签 Java入门 3. 价值 8分 4. 主题 使用面向对象的思路介绍J ...

  5. Effective Java读书笔记(二)

    Effective Java 读书笔记 (二) 创建和销毁对象 遇到多个构造器参数时要考虑使用构建器 创建和销毁对象 何时以及如何创建对象? 何时以及如何避免创建对象? 如何确保它们能够适时地销毁? ...

  6. Effective Java 读书笔记(七):通用程序设计

    Effective Java 读书笔记七通用程序设计 将局部变量的作用域最小化 for-each 循环优于传统的 for 循环 了解和使用类库 如果需要精确的答案请避免使用 float 和 doubl ...

  7. #java读书笔记#面向对象2

    上一篇java读书系列笔记文章:#java读书笔记#面向对象1 14.Math类的使用(重点) (1)数学操作类:该类没有构造函数,方法均为静态的 (2)掌握内容 A:成员变量 **E:比任何其他值都 ...

  8. Effective Java 读书笔记(一)

    前言: 开个新的坑位,<effective java>的读书笔记,之后有时间会陆陆续续的更新,读这本书真的感触满多,item01和item02就已经在公司的项目代码中看到过了.今天这篇主要 ...

  9. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

最新文章

  1. Android中View(视图)绘制不同状态背景图片原理深入分析以及StateListDrawable使用详解...
  2. server新手引导 sql_Web SQL初体验之新手指导(全功能解析)
  3. 你所阅读的,决定你是什么样的人
  4. cin、cin.get()、cin.getline()、getline()、gets()函数的用法
  5. 前向验证对于模型的更新作用
  6. IT结合测试时,准备数据的注意事项(之二:表之间的关系)。
  7. kmem 反编译linux内核_24小时学通Linux内核之如何处理输入输出操作
  8. 黑马程序员传智播客 正则表达式学习笔记 匹配单个字符多个字符
  9. Qt QPushButton 解决触摸屏点击 pressed样式表无效
  10. 数字图像处理和计算机视觉课程大纲,数字图像处理B课程教学大纲.doc
  11. SuperMap iDesktop之夜景特效制作
  12. java总结一:JSON转对象
  13. linux动态库so更新
  14. python批量读取txt数据并写入csv
  15. 华为鸿蒙系统让国产手机用,鸿蒙系统不支持华为手机 系统还是国产手机的命门...
  16. iOS/Android 纪念模式(黑白灰模式) 记录
  17. java服务器如何群发消息,java TCP编程简单实现一个消息群发功能
  18. web浏览器中的javascript
  19. HTTPS能否避免流量劫持?
  20. pandas行/列删除

热门文章

  1. 印象笔记三级目录_我的印象笔记使用手册
  2. 皮卡丘为什么不进化_皮卡丘为啥不进化成雷丘?小智都暗示得这么明显皮卡丘还是拒绝了...
  3. mysql 复杂统计_MYSQL复杂查询
  4. della计算机驱动检测,nexus6安装BPTOOLS中的diag驱动图文教程
  5. 创建微服务架构的步骤_成功备战微服务的5个准备步骤
  6. WebService传输SoapObject数据出现 org.ksoap2.serialization.SoapObject cannot be cast to java.util.Vector的问题
  7. 研究生一年级,非计算机专业,自学机器学习现实吗?
  8. 亚马逊提出无监督虚拟增强句子表征学习框架,效果超越SimCSE
  9. ICLR 2020 | “同步平均教学”框架为无监督学习提供更鲁棒的伪标签
  10. 新型RNN:将层内神经元相互独立以提高长程记忆 | CVPR 2018论文解读