这次这个的思路是在主类中维护一个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——检测其他线程的状态以及启动已死亡的线程的更多相关文章

  1. Java线程:创建与启动

    Java线程:创建与启动 一.定义线程   1.扩展java.lang.Thread类.   此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 R ...

  2. JAVA中线程的状态

    java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW:至今尚未启动的线程的状态. RUNNABLE:可运行线程的线程状态. ...

  3. java中线程的状态详解

    一.线程的五种状态   线程的生命周期可以大致分为5种,但这种说法是比较旧的一种说法,有点过时了,或者更确切的来说,这是操作系统的说法,而不是java的说法.但对下面所说的六种状态的理解有所帮助,所以 ...

  4. 并发基础(四) java中线程的状态

    一.程的五种状态   线程的生命周期可以大致分为5种,但这种说法是比较旧的一种说法,有点过时了,或者更确切的来说,这是操作系统的说法,而不是java的说法.但对下面所说的六种状态的理解有所帮助,所以也 ...

  5. Java多线程之线程的状态迁移

    Java多线程之线程的状态迁移 下图整理了线程的状态迁移.图中的线程状态(Thread.Stat 中定义的Enum 名)NEW.RUNNABLE .TERMINATED.WAITING.TIMED_W ...

  6. 【Java并发编程】:并发新特性—Executor框架与线程池

    Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocur ...

  7. juc线程池原理(四): 线程池状态介绍

    <Thread之一:线程生命周期及五种状态> <juc线程池原理(四): 线程池状态介绍> 线程有5种状态:新建状态,就绪状态,运行状态,阻塞状态,死亡状态.线程池也有5种状态 ...

  8. 用 ThreadPoolExecutor/ThreadPoolTaskExecutor 线程池技术提高系统吞吐量(附带线程池参数详解和使用注意事项)

    1.概述 在Java中,我们一般通过集成Thread类和实现Runnnable接口,调用线程的start()方法实现线程的启动.但如果并发的数量很多,而且每个线程都是执行很短的时间便结束了,那样频繁的 ...

  9. java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器

    多线程并发就像是内功,框架都像是外功,内功不足,外功也难得精要. 1.进程和线程的区别 一个程序至少有一个进程,一个进程至少有一个线程. 用工厂来比喻就是,一个工厂可以生产不同种类的产品,操作系统就是 ...

随机推荐

  1. redis 文件事件模型

    参考文献: 深入剖析 redis 事件驱动 Redis 中的事件循环 深入了解epoll (转) Redis自己的事件模型 ae EPOLL(7) Linux IO模式及 select.poll.ep ...

  2. web前端css(二)

    一.  标准文档流 标准文档流中会有一些现象: 空白折叠 和 高低不齐边底对齐的现象 标准文档流等级森严, 标签分为两种等级: 行内元素 和 块级元素. 1. 行内元素 和 块级元素的区别: 行内元素 ...

  3. 浅谈 Attention 机制的理解

    什么是注意力机制? 注意力机制模仿了生物观察行为的内部过程,即一种将内部经验和外部感觉对齐从而增加部分区域的观察精细度的机制.例如人的视觉在处理一张图片时,会通过快速扫描全局图像,获得需要重点关注的目 ...

  4. Centos7.4 的yum源库配置。

    http://mirrors.163.com/.help/centos.html https://www.cnblogs.com/mchina/archive/2013/01/04/2842275.h ...

  5. Element ui colorpicker在Vue中的使用

    首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker> 在 ...

  6. 使用R语言预测产品销量

    使用R语言预测产品销量 通过不同的广告投入,预测产品的销量.因为响应变量销量是一个连续的值,所以这个问题是一个回归问题.数据集共有200个观测值,每一组观测值对应一种市场情况. 数据特征 TV:对于一 ...

  7. linux svn 中文 https://my.oschina.net/VASKS/blog/659236

    https://my.oschina.net/VASKS/blog/659236 设置服务器: export LC_ALL=zh_CN.UTF-8长久之计, echo export LC_ALL=zh ...

  8. Flutter学习笔记(9)--组件Widget

    如需转载,请注明出处:Flutter学习笔记(9)--组件Widget 在Flutter中,所有的显示都是Widget,Widget是一切的基础,我们可以通过修改数据,再用setState设置数据(调 ...

  9. 机器学习-EM算法

    最大期望算法 EM算法的正式提出来自美国数学家Arthur Dempster.Nan Laird和Donald Rubin,其在1977年发表的研究对先前出现的作为特例的EM算法进行了总结并给出了标准 ...

  10. 面向对象和pickle模块结合

    面向对象和pickle模块相关 1.面向对象: class 类名: def init(self,参数1,参数2): self.对象的属性1 = 参数1 self.对象的属性2 = 参数2 def 方法 ...