Java——检测其他线程的状态以及启动已死亡的线程
这次这个的思路是在主类中维护一个map,map的key是线程名,value是线程的状态,然后创建周期执行的线程通过检测这个map来判断进程的状态,如果有死亡的进程就把该进程启动。
首先是主类,这里的main方法中为了执行结果简单易懂 ,先是初始化了一个长度为2的newFixedThreadPool线程池,然后提交了2个任务(这个任务类下面会有介绍),然后启动监控线程,这个监控线程也是一会介绍,其他方法的作用注释写得也很清楚:
public class Test {
/** Log4j 初始化 */
private static final Logger logger = LoggerFactory.getLogger(Test.class);
/** 标志线程存活的变量 */
public static final int THREAD_STATUS_ALIVE = 1;
/** 标志线程死亡的变量 */
public static final int THREAD_STATUS_DEAD = 0;
/** 记录每个线程的状态的map */
private static HashMap<String,Integer> threadStatesMap = new HashMap<String, Integer>();
/** 线程池的长度*/
private static int threadPoolLength;
/** 创建固定长度的线程池 */
private static ExecutorService executor;
public static void main(String[] args) {
/** 初始化线程池 */
executor = Executors.newFixedThreadPool(2);
/** 提交Task给线程池 */
for(int i = 1; i <= 2; i++){
executeToPool(new EtlTask(i));
}
Monitor monitor = new Monitor();
/** 启动检测线程 */
monitor.start();
}
/**
* 根据线程名,更新线程的状态
* @param threadName
* @param status
*/
public synchronized static void alterThreadStatesMap(String threadName,Integer status){
threadStatesMap.put(threadName,status);
}
/**
* 返回ThreadStatesMap的长度
* @return
*/
public static int getThreadStatesMapSize(){
return threadStatesMap.size();
}
/**
* 返回key对应ThreadStatesMap的value
* @param key
* @return ThreadStatesMapValueByKey
*/
public static int getThreadStatesMapValueByKey(String key){
return threadStatesMap.get(key);
}
/**
* 提交任务给线程池
* @param etlTask
*/
public static void executeToPool(EtlTask etlTask){
executor.execute(etlTask);
}
}
然后创建一个会报异常的测试类(id每一秒减一次1,到0的时候抛异常):
/**
* 测试线程
*/
class testThread {
private static Logger logger = LoggerFactory.getLogger(testThread.class);
public static void start(int id) throws Exception{
id = id + 5;
while (true){
try {
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
id = id - 1;
if(id == 0){
//id每一秒减一次1,到0的时候抛异常
throw new Exception();
}
logger.debug(Thread.currentThread().getName() + " is running result = " + id );
} }
}
然后创建一个执行上面测试任务的任务类,这里在第一次被启动的时候会设置好该任务类的名字,将主类中的map中线程名对应的value设置为THREAD_STATUS_ALIVE,然后开始执行上面的测试任务,如果有异常的话会将主类中的map中线程名对应的value设置为THREAD_STATUS_DEAD:
/**
* 任务线程
*/
class EtlTask implements Runnable{
/** 组ID */
private int groupid ;
/** 初始化组ID */
EtlTask(int groupid){
this.groupid = groupid;
}
public void run() {
/** 设置线程名 */
Thread.currentThread().setName("G" + groupid);
/** 设置线程的 运行状态为THREAD_STATUS_ALIVE 在ThreadStatesMap中*/
Test.alterThreadStatesMap(Thread.currentThread().getName(),Test.THREAD_STATUS_ALIVE);
try{
/** 将组ID传入,执行任务*/
testThread.start(groupid);
}catch (Exception e ){
/** 出现异常 设置线程的 运行状态为THREAD_STATUS_DEAD 在ThreadStatesMap中*/
Test.alterThreadStatesMap(Thread.currentThread().getName(),Test.THREAD_STATUS_DEAD);
} }
}
最后就是监控类,这个类就是在遍历主类中的map,有死亡的线程就启动该线程。
/**
* 监控线程
*/
class Monitor extends Thread{
private static final Logger logger = LoggerFactory.getLogger(Monitor.class);
public void run() {
while(true){
try {
Thread.sleep(5000);//监控线程阻塞5秒后运行
}catch (Exception e){
e.printStackTrace();
} logger.debug("Current total [" + Test.getThreadStatesMapSize() +"] threads");
/** 线程存活数 */
int alives = 0;
/** 线程死亡数 */
int deads = 0;
/** 遍历ThreadStatesMap 计算线程存活数和死亡数 */
for(int i = 1;i <= Test.getThreadStatesMapSize();i++){
if(Test.getThreadStatesMapValueByKey("G" + i) == Test.THREAD_STATUS_ALIVE){
alives++;
}else {
deads++;
}
}
logger.debug("Current the number of threads alive is [" + alives +"]");
logger.debug("Current the number of threads dead is [" + deads +"]");
/** 如果死亡线程数大于0 就启动已经死亡的线程 */
if(deads > 0) {
/** 遍历ThreadStatesMap 将死亡的线程启动 */
for (int i = 1; i <= Test.getThreadStatesMapSize(); i++) {
if (Test.getThreadStatesMapValueByKey("G" + i) == Test.THREAD_STATUS_DEAD) {
/** 向线程池提交任务 */
Test.executeToPool(new EtlTask(i));
logger.debug("Thread G" + i + "已被启动");
}
}
}
}
}
}
效果:
2018-08-02 16:24:31,649 - G2 is running result = 6
2018-08-02 16:24:31,655 - G1 is running result = 5
2018-08-02 16:24:32,653 - G2 is running result = 5
2018-08-02 16:24:32,656 - G1 is running result = 4
2018-08-02 16:24:33,653 - G2 is running result = 4
2018-08-02 16:24:33,656 - G1 is running result = 3
2018-08-02 16:24:34,653 - G2 is running result = 3
2018-08-02 16:24:34,656 - G1 is running result = 2
2018-08-02 16:24:35,635 - Current total [2] threads
2018-08-02 16:24:35,635 - Current the number of threads alive is [2]
2018-08-02 16:24:35,635 - Current the number of threads dead is [0]
2018-08-02 16:24:35,654 - G2 is running result = 2
2018-08-02 16:24:35,657 - G1 is running result = 1
2018-08-02 16:24:36,654 - G2 is running result = 1
2018-08-02 16:24:40,635 - Current total [2] threads
2018-08-02 16:24:40,635 - Current the number of threads alive is [0]
2018-08-02 16:24:40,635 - Current the number of threads dead is [2]
2018-08-02 16:24:40,635 - Thread G1已被启动
2018-08-02 16:24:40,635 - Thread G2已被启动
2018-08-02 16:24:41,635 - G2 is running result = 6
2018-08-02 16:24:41,635 - G1 is running result = 5
2018-08-02 16:24:42,636 - G1 is running result = 4
2018-08-02 16:24:42,636 - G2 is running result = 5
2018-08-02 16:24:43,636 - G2 is running result = 4
2018-08-02 16:24:43,636 - G1 is running result = 3
2018-08-02 16:24:44,637 - G2 is running result = 3
2018-08-02 16:24:44,637 - G1 is running result = 2
2018-08-02 16:24:45,636 - Current total [2] threads
2018-08-02 16:24:45,636 - Current the number of threads alive is [2]
2018-08-02 16:24:45,636 - Current the number of threads dead is [0]
2018-08-02 16:24:45,637 - G1 is running result = 1
2018-08-02 16:24:45,637 - G2 is running result = 2
2018-08-02 16:24:46,637 - G2 is running result = 1
2018-08-02 16:24:50,636 - Current total [2] threads
2018-08-02 16:24:50,636 - Current the number of threads alive is [0]
2018-08-02 16:24:50,636 - Current the number of threads dead is [2]
2018-08-02 16:24:50,636 - Thread G1已被启动
2018-08-02 16:24:50,636 - Thread G2已被启动
2018-08-02 16:24:51,637 - G2 is running result = 6
2018-08-02 16:24:51,637 - G1 is running result = 5
2018-08-02 16:24:52,637 - G1 is running result = 4
2018-08-02 16:24:52,637 - G2 is running result = 5 Process finished with exit code -1
从控制台的输出日志可以看到,两个线程的结果到0的时候死亡了,然后会被监控进程启动。
Java——检测其他线程的状态以及启动已死亡的线程的更多相关文章
- Java线程:创建与启动
Java线程:创建与启动 一.定义线程 1.扩展java.lang.Thread类. 此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 R ...
- JAVA中线程的状态
java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW:至今尚未启动的线程的状态. RUNNABLE:可运行线程的线程状态. ...
- java中线程的状态详解
一.线程的五种状态 线程的生命周期可以大致分为5种,但这种说法是比较旧的一种说法,有点过时了,或者更确切的来说,这是操作系统的说法,而不是java的说法.但对下面所说的六种状态的理解有所帮助,所以 ...
- 并发基础(四) java中线程的状态
一.程的五种状态 线程的生命周期可以大致分为5种,但这种说法是比较旧的一种说法,有点过时了,或者更确切的来说,这是操作系统的说法,而不是java的说法.但对下面所说的六种状态的理解有所帮助,所以也 ...
- Java多线程之线程的状态迁移
Java多线程之线程的状态迁移 下图整理了线程的状态迁移.图中的线程状态(Thread.Stat 中定义的Enum 名)NEW.RUNNABLE .TERMINATED.WAITING.TIMED_W ...
- 【Java并发编程】:并发新特性—Executor框架与线程池
Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocur ...
- juc线程池原理(四): 线程池状态介绍
<Thread之一:线程生命周期及五种状态> <juc线程池原理(四): 线程池状态介绍> 线程有5种状态:新建状态,就绪状态,运行状态,阻塞状态,死亡状态.线程池也有5种状态 ...
- 用 ThreadPoolExecutor/ThreadPoolTaskExecutor 线程池技术提高系统吞吐量(附带线程池参数详解和使用注意事项)
1.概述 在Java中,我们一般通过集成Thread类和实现Runnnable接口,调用线程的start()方法实现线程的启动.但如果并发的数量很多,而且每个线程都是执行很短的时间便结束了,那样频繁的 ...
- java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器
多线程并发就像是内功,框架都像是外功,内功不足,外功也难得精要. 1.进程和线程的区别 一个程序至少有一个进程,一个进程至少有一个线程. 用工厂来比喻就是,一个工厂可以生产不同种类的产品,操作系统就是 ...
随机推荐
- java获取config下文件
private static final String keystore="keystore.jks"; InputStream is=Thread.currentThread() ...
- easyui datagrid 单元格 编辑时 事件 修改另一单元格
//datagrid 列数据 $('#acc').datagrid({ columns : [ [ { field : 'fee_lend', title : '收费A', width : 100, ...
- InnoDB存储引擎--学习笔记-redo log
目录 1. 引言 2. 重做日志文件和相关概念介绍 + 2.1. 重做日志文件和bin log + 2.2. LSN(log squence number) 3. 重做日志文件基本工作原理 4. 重做 ...
- Tensorflow教程(2)Tensorflow的常用函数介绍
1.tf.constant tf.constant用来定义一个常量,所谓常量,广义上讲就是“不变化的量”.我们先看下官方api是如何对constant函数来定义的: tf.constant( valu ...
- java unicode补充字符带来的码点和代码单元问题
码点与代码单元 java string有两种判定字符的方式,一种是以码点,一种以代码单元,简单讲,码点就是真正的字符,代码单元是按大小即char型长度2个字节划分字符串. 所以length和chara ...
- nu.xom:Document
Document: 机翻 Document(Document doc):创建此文档的副本. Document(Element root):使用指定的根元素创建新的Document对象. DocType ...
- 企业如何从“API优先”的策略中获益
在过去的几年里,全球API经济在以难以置信的速度进行快速地增长.物联网.人工智能.自动驾驶等等众多令人充满期待的技术正蓬勃发展,这也证明了API对于如今整个技术圈子的重要性,也预示着在不久的将来它还将 ...
- [原创]Rsync搭建和使用
rsync服务的搭建和使用 ***下载安装: #wget https://download.samba.org/pub/rsync/src/rsync-3.1.2.tar.gz #tar -zxvf ...
- 搭建oj平台
欢迎使用https://github.com/QingdaoU/OnlineJudgeDeploy
- 地图组件demo
高德地图API(demo未完善) 1:声请JSAPI的key值:http://lbs.amap.com/dev/#/(已声请key名称:demo-javascipt key:7cbbed2d9a0c0 ...