先复习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重启线程的更多相关文章

  1. java UncaughtExceptionHandler 处理线程意外中止

    本文转自:http://peirenlei.iteye.com/blog/305079 Thread的run方法是不抛出任何检查型异常(checked exception)的,但是它自身却可能因为一个 ...

  2. Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程

    Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程 一.捕获异常并重新启用线程 public class Testun { public static voi ...

  3. python通过重启线程,实现服务的热加载

    这个思路后来证明不能用于工作. 因为线程调用没有及时返回,所以不能用这种方式来重启服务. 但作为脑洞,也应该作个记录. import os import shutil import datetime ...

  4. Android Priority Job Queue (Job Manager):线程任务的容错重启机制(二)

     Android Priority Job Queue (Job Manager):线程任务的容错重启机制(二) 附录文章4简单介绍了如何启动一个后台线程任务,Android Priority J ...

  5. .net重启iis线程池和iis站点程序代码【转】

    转:http://www.jb51.net/article/44162.htm 重启站点: 复制代码代码如下:  /// <summary>        /// 根据名字重启站点.(没重 ...

  6. .net重启iis线程池和iis站点程序代码分享

    重启站点: /// <summary> /// 根据名字重启站点.(没重启线程池) /// </summary> /// <param name="sitena ...

  7. Java线程监听,意外退出线程后自动重启

    Java线程监听,意外退出线程后自动重启 某日,天朗气清,回公司,未到9点,刷微博,顿觉问题泛滥,惊恐万分! 前一天写了一个微博爬行程序,主要工作原理就是每隔2分钟爬行一次微博,获取某N个关注朋友微博 ...

  8. 重启iis线程池和iis站点

    服务器监控. 一定时间内或者iis异常,就重启线程池和站点 一般重启站点没啥用.. 重启线程池 效果明显. 重启站点: /// <summary> /// 根据名字重启站点.(没重启线程池 ...

  9. Android Priority Job Queue (Job Manager):后台线程任务结果传回前台(三)

     Android Priority Job Queue (Job Manager):后台线程任务结果传回前台(三) 在附录文章4,5的基础上改造MainActivity.java和MyJob.ja ...

随机推荐

  1. 洛谷P1441 砝码称重(搜索,dfs+bitset优化)

    洛谷P1441 砝码称重 \(n\) 的范围为 \(n \le 20\) ,\(m\) 的范围为 \(m \le 4\) . 暴力遍历每一种砝码去除情况,共有 \(n^m\) 种情况. 对于剩余砝码求 ...

  2. Windows命令学习

    总: 1.window dos命令不区分大小写  2.指令参数 /a   -a 等价 更倾向于 / 3.命令有疑问: CMD输入help 或者单条命令 /? help time /? 用到的实用命令总 ...

  3. 奖项-MVP:MVP(微软最有价值专家)百科

    ylbtech-奖项-MVP:MVP(微软最有价值专家)百科 微软最有价值专家(MVP) 是指具备一种或多种微软技术专业知识,并且积极参与在线或离线的社群活动,经常与其他专业人士分享知识和专业技能,受 ...

  4. MySQL-创建测试数据

    简单的方法(每次增加一倍): insert into tb_user(f_id, f_username) select rand(), f_username from tb_user

  5. tomcat 迁移到weblogic 问题

    问题1: Caused by: java.lang.UnsupportedClassVersionError: com/audaque/datadiscovery/soap/service/impl/ ...

  6. AtCoder ABC 140D Face Produces Unhappiness

    题目链接:https://atcoder.jp/contests/abc140/tasks/abc140_d 题目大意 有一对 N 个人, 用字符串 S 表示, S[i] 如果等于 'L' 说明这个人 ...

  7. MySQL- 查询总结

    查询总结 语法: select 查询字段 from 表 别名 连接类型inner|left|right join on 连接条件 where 筛选 group by 分组列表 having 筛选(二次 ...

  8. JavaScript 高级程序设计(第3版)第一章 (js简介)

    1.我比js早一年 2.web浏览器是ECMAScript实现的宿主环境之一. 其它实现ECMAScript的宿主环境包括Node和Adobe Flash 3.ECMAScript主要规定js的组成部 ...

  9. LOJ 2183 / SDOI2015 序列统计 (DP+矩阵快速幂)

    题面 传送门 分析 考虑容斥原理,用总的方案数-不含质数的方案数 设\(dp1[i][j]\)表示前i个数,和取模p为j的方案数, \(dp2[i][j]\)表示前i个数,和取模p为j的方案数,且所有 ...

  10. 【问题解决方案】关于Python中的语句 ' %matplotlib inline '

    跟进小项目#GirlsInAI#-可视化时遇到的语句,之前没有遇到过 在Stack Overflow上看到了一个解释: IPython有一组预定义的"魔术函数",您可以使用命令行样 ...