先复习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. 阿里云不支持stmp 的25端口,必须

    第一种方法 到阿里云解封25端口 特别注意阿里云的<25端口使用服务协议>:    我/我公司承诺并保证TCP 25端口仅用来连接第三方的SMTP服务器,从第三方的SMTP服务器外发邮件. ...

  2. HDU6599:求本质不同的子串(回文串)长度及数量

    目录 hdu6599题意: manacher+后缀自动机+倍增 \(O(nlog(n))\) manacher+后缀数组+二分 \(O(nlog(n))\) 回文树(回文自动机) \(O(n)\) @ ...

  3. 清北学堂Day 6之STL

    电脑突然一炸,什么都没有保存,凉了.(又出现了笔记凉凉事件嘤嘤嘤) 行吧慢慢回忆 就算我们会手写,我们也要学STL.吸了O2的STL可是要上天的. 数据结构 pair 使用方式: pair<类型 ...

  4. spring4.1.8扩展实战之五:改变bean的定义(BeanFactoryPostProcessor接口)

    本章我们继续实战spring的扩展能力,通过自定义BeanFactoryPostProcessor接口的实现类,来对bean实例做一些控制: 原文地址:https://blog.csdn.net/bo ...

  5. windows10上使用一个tomcat部署2个项目

    前言:目前想在本机部署2个项目,网上查了之后,写下本篇随笔 1.准备工作 2.操作方法 3.运行2个项目 1.准备工作 2个war包(一个jprss.war和一个jenkins.war) 1个tomc ...

  6. python 微服务方案

    介绍 使用python做web开发面临的一个最大的问题就是性能,在解决C10K问题上显的有点吃力.有些异步框架Tornado.Twisted.Gevent 等就是为了解决性能问题.这些框架在性能上有些 ...

  7. 【ABAP系列】SAP SAP中关于编码的解释

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP SAP中关于编码的解释 ...

  8. 简单的C++11线程池实现

    线程池的C++11简单实现,源代码来自Github上作者progschj,地址为:A simple C++11 Thread Pool implementation,具体博客可以参见Jakob's D ...

  9. win10下装win7双系统安装教程

    win10下装win7双系统安装教程 来源:www.laomaotao.org 时间:2017-02-13 10:15 新买的电脑预装了win10系统,但win10对于有些游戏兼容性不是很好,总是会出 ...

  10. Swipe-移动端触摸滑动插件swipe.js

    原文链接:http://caibaojian.com/swipe.html 插件特色 viaswipe.JS是一个比较有名的触摸滑动插件,它能够处理内容滑动,支持自定义选项,你可以让它自动滚动,控制滚 ...