日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2024/9/30 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【java读书笔记】ThreadGroup和钩子线程的使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • ThreadGroup介紹
    • ThreadGroup的基本操作
    • ThreadGroup的其他方法
  • 鉤子線程
    • 用hook線程模擬防重復(fù)啟動(dòng)程序

ThreadGroup介紹

ThreadGroup并不能提供對(duì)線程的管理,ThreadGroup的主要功能是對(duì)線程進(jìn)行組織,下面將詳細(xì)介紹ThreadGroup的主要方法。

ThreadGroup的基本操作

activeCount()用于獲取group中活躍的線程,這只是個(gè)估計(jì)值,并不能百分之百地保證數(shù)字一定正確,原因前面已經(jīng)分析過(guò),該方法會(huì)遞歸獲取其他子group中的活躍線程。

activeGroupCount()用于獲取group中活躍的子group,這也是一個(gè)近似估值,該方法也會(huì)遞歸獲取所有的子group。

getMaxPriority()用于獲取group的優(yōu)先級(jí),默認(rèn)情況下,Group的優(yōu)先級(jí)為10,在該group中,所有線程的優(yōu)先級(jí)都不能大于group的優(yōu)先級(jí)

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

getParent()用于獲取group的父group,如果父group不存在,則會(huì)返回null,比如system group的父group就為null。 list()該方法沒(méi)有返回值,執(zhí)行該方法會(huì)將group中所有的活躍線程信息全部輸出到控制臺(tái),也就是System.out。

parentOf(ThreadGroup g)會(huì)判斷當(dāng)前group是不是給定group的父group,另外如果給定的group就是自己本身,那么該方法也會(huì)返回true。

setMaxPriority(int pri)會(huì)指定group的最大優(yōu)先級(jí),最大優(yōu)先級(jí)不能超過(guò)父group的最大優(yōu)先級(jí),執(zhí)行該方法不僅會(huì)改變當(dāng)前group的最大優(yōu)先級(jí),還會(huì)改變所有子group的最大優(yōu)先級(jí)。 下面我們給出一個(gè)簡(jiǎn)單的例子來(lái)測(cè)試一下上面的幾個(gè)方法。

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));}}

這里需要特別說(shuō)明的是setMaxPriority,我們通過(guò)分析源碼得出結(jié)論,線程的最大優(yōu)先級(jí),不能高于所在線程組的最大優(yōu)先級(jí),但是如果我們把代碼寫(xiě)成下面這樣會(huì)怎么樣呢?

ThreadGroup的其他方法

ThreadGroup的interrupt

interrupt一個(gè)thread group會(huì)導(dǎo)致該group中所有的active線程都被interrupt,也就是說(shuō)該group中每一個(gè)線程的interrupt標(biāo)識(shí)都被設(shè)置了

ThreadGroup的destroy
destroy用于銷毀ThreadGroup,該方法只是針對(duì)一個(gè)沒(méi)有任何active線程的group進(jìn)行一次destroy標(biāo)記,調(diào)用該方法的直接結(jié)果是在父group中將自己移除:

鉤子線程

JVM進(jìn)程的退出是由于JVM進(jìn)程中沒(méi)有活躍的非守護(hù)線程,或者收到了系統(tǒng)中斷信號(hào),向JVM程序注入一個(gè)Hook線程,在JVM進(jìn)程退出的時(shí)候,Hook線程會(huì)啟動(dòng)執(zhí)行,通過(guò)Runtime可以為JVM注入多個(gè)Hook線程,下面就通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)看一下如何向Java程序注入Hook線程。

ThreadHook.java package com.wangwenjun.concurrent.chapter07;import java.util.concurrent.TimeUnit;public class ThreadHook {public static void main(String[] args){//為應(yīng)用程序注入鉤子線程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.");}});//鉤子線程可注冊(cè)多個(gè)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程序注入了兩個(gè)Hook線程,在main線程中結(jié)束,也就是JVM中沒(méi)有了活動(dòng)的非守護(hù)線程,JVM進(jìn)程即將退出時(shí),兩個(gè)Hook線程會(huì)被啟動(dòng)并且運(yùn)行,輸出結(jié)果如下:

在我們的開(kāi)發(fā)中經(jīng)常會(huì)遇到Hook線程,比如為了防止某個(gè)程序被重復(fù)啟動(dòng),在進(jìn)程啟動(dòng)時(shí)會(huì)創(chuàng)建一個(gè)lock文件,進(jìn)程收到中斷信號(hào)的時(shí)候會(huì)刪除這個(gè)lock文件,我們?cè)趍ysql服務(wù)器、zookeeper、kafka等系統(tǒng)中都能看到lock文件的存在,本節(jié)中,將利用hook線程的特點(diǎn),模擬一個(gè)防止重復(fù)啟動(dòng)的程序,

用hook線程模擬防重復(fù)啟動(dòng)程序

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線程,在程序退出時(shí)刪除lock文件Runtime.getRuntime().addShutdownHook(new Thread(() ->{System.out.println("The program received kill SIGNAL.");getLockFile().toFile().delete();}));//② 檢查是否存在.lock文件checkRunning();//③ 簡(jiǎn)單模擬當(dāng)前程序正在運(yùn)行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);} }

運(yùn)行上面的程序,會(huì)發(fā)現(xiàn)在/home/wangwenjun/locks目錄下多了一個(gè).lock文件,程序運(yùn)行則會(huì)創(chuàng)建.lock文件以防止重復(fù)啟動(dòng)
執(zhí)行kill pid或者kill-1 pid命令之后,JVM進(jìn)程會(huì)收到中斷信號(hào),并且啟動(dòng)hook線程刪除.lock文件。

Hook線程是一個(gè)非常好的機(jī)制,可以幫助程序獲得進(jìn)程中斷信號(hào),有機(jī)會(huì)在進(jìn)程退出之前做一些資源釋放的動(dòng)作,或者做一些告警通知。切記如果強(qiáng)制殺死進(jìn)程,那么進(jìn)程將不會(huì)收到任何中斷信號(hào)。

注:筆記來(lái)自書(shū)籍《java高并發(fā)編程詳解》

總結(jié)

以上是生活随笔為你收集整理的【java读书笔记】ThreadGroup和钩子线程的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。