使用UncaughtExceptionHandler重启线程
先复习Java中的异常
java.lang.Throwable 顶层父类
|– Error错误:JVM内部的严重问题,如OOM,程序员无法在代码中无法处理。
|–Exception异常:普通的问题。通过合理的处理,程序还可以回到正常执行流程。要求程序员要进行处理。
|–RuntimeException:未检查异常(unchecked exception)。 这类异常是程序员的逻辑问题,由于程序员的疏忽导致的错误(如数组越界,空指针等)。
Java编译器不进行强制要求处理。 也就是说,这类异常在程序中,可以进行处理,也可以不处理。
|–非RuntimeException:已检查异常(checked exception)、编译时异常。这类异常是由一些外部的偶然因素所引起的。Java编译器强制要求处理。也就是说,
程序必须进行对这类异常进行处理,throw,throws或者try catch。
而线程Thread的的run()方法不接受抛出语句,因此对于已检查异常,我们必须进行捕获并处理,如:
@Override
public void run() {
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(""));
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
}
而对于未检查异常,如果在run()方法中运行出现了未检查异常,那么默认的行为是将堆栈跟踪信息写到控制台中(或者记录到错误日志文件中),然后退出程序。
Java为我们提供了一个机制,用来捕获并处理在一个线程对象中抛出的未检查异常,以避免程序终止。用UncaughtExceptionHandler来实现这种机制。
不使用UncaughtExceptionHandler的场景:
public class MyThread implements Runnable {
@Override
public void run() {
Integer.parseInt("yangyongjie");
System.out.println("expect");
}
}
控制台输出:
Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "yangyongjie"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at com.yang.spbo.other.thread.MyThread.run(MyThread.java:15)
at java.lang.Thread.run(Thread.java:745)
此时,线程立即终止,并没有执行之后的代码输出字符串“expect”。若在执行很重要的代码之前,出现了未检查异常,导致了线程终止,那么就会导致业务异常。
使用UncaughtExceptionHandler后:
首先,自定义异常处理器实现UncaughtExceptionHandler接口,用来捕获和处理运行时出现的未检查异常(RuntimeException)
public class CustomUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomUncaughtExceptionHandler.class);
/**
* 可以自定义处理方案,如不断重试、将异常任务存入数据库等
*
* @param t
* @param e
*/
@Override
public void uncaughtException(Thread t, Throwable e) {
LOGGER.error("An exception has been captured,Thread: {}", t.getId());
LOGGER.error("Exception: {}: {}", e.getClass().getName(), e.getMessage());
LOGGER.error("Thread status: {}", t.getState());
new Thread(new MyThread()).start();
}
}
接着,将异常处理器添加到线程中
public class MyThread implements Runnable {
@Override
public void run() {
// 异常处理器
Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
Integer.parseInt("yangyongjie");
System.out.println("expect");
}
}
再次运行,程序能够持续执行run方法。实际上,如果线程完成了任务,那么它在退出时不会抛出任何异常,从而完成自身生命周期
An exception has been captured
Thread: 10
Exception: java.lang.NumberFormatException: For input string: "yangyongjie"
Stack Trace:
java.lang.NumberFormatException: For input string: "yangyongjie"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at com.yang.spbo.other.thread.MyThread.run(MyThread.java:22)
at java.lang.Thread.run(Thread.java:745)
Thread status: RUNNABLE
An exception has been captured
Thread: 12
Exception: java.lang.NumberFormatException: For input string: "yangyongjie"
Stack Trace:
java.lang.NumberFormatException: For input string: "yangyongjie"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at com.yang.spbo.other.thread.MyThread.run(MyThread.java:22)
at java.lang.Thread.run(Thread.java:745)
Thread status: RUNNABLE
请注意:UncaughtExceptionHandler可以在无需重启线程的条件下,将日志记录变得更加健壮,因为默认日志在线程执行失败时,不会提供足够的上下文信息。
线程池异常处理,自定义创建线程的工厂,在创建线程时指定
/**
* 创建线程的工厂,指定有意义的线程组名称,方便回溯
*
* @author yangyongjie
* @date 2019/8/14
* @desc
*/
public class CustomThreadFactory implements ThreadFactory {
/**
* 线程池中的线程名称前缀
*/
private String namePrefix; /**
* 用于线程的名称递增排序
*/
private AtomicInteger atomicInteger = new AtomicInteger(1); public CustomThreadFactory(String whatFeaturOfGroup) {
this.namePrefix = "From CustomThreadFactory-" + whatFeaturOfGroup + "-worker-";
} @Override
public Thread newThread(Runnable r) {
String name = namePrefix + atomicInteger.getAndIncrement();
Thread thread = new Thread(r, name);
thread.setUncaughtExceptionHandler(new CustomUncaughtExceptionHandler());
return thread;
}
} /**
* 用来捕获和处理运行时出现的未检查异常(RuntimeException)
* 并重启线程
*
* @author yangyongjie
* @date 2019/11/26
* @desc
*/
public class CustomUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { private static final Logger LOGGER = LoggerFactory.getLogger(CustomUncaughtExceptionHandler.class); /**
* 可以自定义处理方案,如不断重试、将异常任务存入数据库等
*
* @param t
* @param e
*/
@Override
public void uncaughtException(Thread t, Throwable e) {
LOGGER.error("uncaughtException:" + e.getMessage(), e);
MDCUtil.removeWithOutContext();
}
}
使用UncaughtExceptionHandler重启线程的更多相关文章
- java UncaughtExceptionHandler 处理线程意外中止
本文转自:http://peirenlei.iteye.com/blog/305079 Thread的run方法是不抛出任何检查型异常(checked exception)的,但是它自身却可能因为一个 ...
- Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程
Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程 一.捕获异常并重新启用线程 public class Testun { public static voi ...
- python通过重启线程,实现服务的热加载
这个思路后来证明不能用于工作. 因为线程调用没有及时返回,所以不能用这种方式来重启服务. 但作为脑洞,也应该作个记录. import os import shutil import datetime ...
- Android Priority Job Queue (Job Manager):线程任务的容错重启机制(二)
Android Priority Job Queue (Job Manager):线程任务的容错重启机制(二) 附录文章4简单介绍了如何启动一个后台线程任务,Android Priority J ...
- .net重启iis线程池和iis站点程序代码【转】
转:http://www.jb51.net/article/44162.htm 重启站点: 复制代码代码如下: /// <summary> /// 根据名字重启站点.(没重 ...
- .net重启iis线程池和iis站点程序代码分享
重启站点: /// <summary> /// 根据名字重启站点.(没重启线程池) /// </summary> /// <param name="sitena ...
- Java线程监听,意外退出线程后自动重启
Java线程监听,意外退出线程后自动重启 某日,天朗气清,回公司,未到9点,刷微博,顿觉问题泛滥,惊恐万分! 前一天写了一个微博爬行程序,主要工作原理就是每隔2分钟爬行一次微博,获取某N个关注朋友微博 ...
- 重启iis线程池和iis站点
服务器监控. 一定时间内或者iis异常,就重启线程池和站点 一般重启站点没啥用.. 重启线程池 效果明显. 重启站点: /// <summary> /// 根据名字重启站点.(没重启线程池 ...
- Android Priority Job Queue (Job Manager):后台线程任务结果传回前台(三)
Android Priority Job Queue (Job Manager):后台线程任务结果传回前台(三) 在附录文章4,5的基础上改造MainActivity.java和MyJob.ja ...
随机推荐
- codeforces 617 E. XOR and Favorite Number(莫队算法)
题目链接:http://codeforces.com/problemset/problem/617/E 题目: 给你a1 a2 a3 ··· an 个数,m次询问:在[L, R] 里面又多少中 [l, ...
- crfclust.bdb导致磁盘满
检查ora.crf服务 crsctl stat res ora.crf -init -t 关闭ora.crf服务 crsctl stop res ora.crf -init cd $ORACLE_HO ...
- python简单的函数定义和用法实例
python简单的函数定义和用法实例 这篇文章主要介绍了python简单的函数定义和用法,实例分析了Python自定义函数及其使用方法,具有一定参考借鉴价值,需要的朋友可以参考下 具体分析如下: 这里 ...
- Xpath表达式的粗介绍
关于在自动化中Xpath表达式的书写,其实我也只是刚刚入门,粗略的跟着网上的教程学了一下,这篇我就来分享总结一下我学习到的知识. 首先呢,我们先认识一下什么是Xpath.Xpath是XML路径语言,它 ...
- 网络流强化-POJ2516
k种货物分开求解最小费用最大流,主要减少了寻找最短路的时间. #include<queue> #include<cstdio> #include<cstring> ...
- 机器学习实战笔记-10-K均值聚类
K-均值聚类 优点:易实现.缺点:可能收敛到局部最小值,大规模数据集上收敛较慢:适用于数值型数据. K-均值聚类(找到给定数据集的k个簇) 算法流程 伪代码: 创建k个点作为起始质心(经常是随机选择) ...
- dubbo入门和springboot集成dubbo小例子
从零开始搭建springboot-dubbo的例子 Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案 一. Dubbo的简单介绍 1. ...
- ichunqiu在线挑战--我很简单,请不要欺负我 writeup
挑战链接: http://www.ichunqiu.com/tiaozhan/114 知识点: 后台目录扫描,SQL Injection,一句话木马, 提权,登陆密码破解 这个挑战是为像我这种从来都没 ...
- oracle用户权限管理
oralce对权限管理比较严谨,普通用户之间也是默认不能互相访问的,需要互相授权 1.查看当前数据库所有用户: select * from all_users; 2.查看表所支持的权限: select ...
- 32.Group Anagrams(相同元素的不同组合)
Level: Medium 题目描述: Given an array of strings, group anagrams together. Example: Input: ["eat ...