资讯专栏INFORMATION COLUMN

一起学并发编程 - 处理异常中止的线程

zacklee / 2283人阅读

摘要:在之前,不能为线程多带带设置或指定一个默认的,为了设置,需要继承并覆写方法。幸运的是后线程提供了一个方法,用来捕获并处理因线程中抛出的未知异常,以避免程序终止。

单线程的开发过程中,通常采用try-catch的方式进行异常捕获,但是这种方式在多线程环境中会显得无能为力,而且还有可能导致一些问题的出现,比如发生异常的时候不能及时回收系统资源,或者无法及时关闭当前的连接...

概述

Java中有两种异常,即已知异常(编辑器会提示捕获或者抛出)未知异常(特殊情况下发生),由于线程中的run()方法是不接受抛出语句的(只能内部捕获),所以在面对未知异常的情况,线程默认的会将堆栈跟踪信息输出到控制台中(或者记录到错误日志文件中)然后退出程序。

JDK1.5之前,不能为线程多带带设置或指定一个默认的UncaughtExceptionHandler,为了设置UncaughtExceptionHandler,需要继承ThreadGroup并覆写uncaughtException方法。 幸运的是JDK1.5后线程提供了一个setUncaughtExceptionHandler方法,用来捕获并处理因线程中抛出的未知异常,以避免程序终止。

案例

1.首先模拟一个连接池,提供

class ConnectionPool {
    static void create() {
        System.out.println("初始化连接池...");
    }
    static void close() {
        System.out.println("关闭连接池...");
    }
}

2.为了测试需要,只是简单模拟了一个异常

public static void main(String[] args) {
    ConnectionPool.create();
    try {
        //有个任务需要异步执行
        Thread thread = new Thread(() -> System.out.println(Integer.parseInt("ABC")), "T2");
        thread.start();
    } catch (Exception e) {
        ConnectionPool.close();
    }
}

分析: 从日志中,并未发现关闭资源应有的日志输出,很明显try-catch没有起作用,因为在main函数中他是主线程,当thread.start()之后,主线程的代码与子线程就没半毛钱关系了,所以发生在子线程内部的错误无法捕获到。

解决方案

使用UncaughtExceptionHandler,这里为了偷懒使用了lambda简化了匿名内部类的写法(也可以实现UncaughtExceptionHandler

public static void main(String[] args) {
    ConnectionPool.create();
    Thread thread = new Thread(() -> System.out.println(Integer.parseInt("ABC")), "T1");
    thread.start();
    thread.setUncaughtExceptionHandler((t, e) -> {
        System.out.println("[线程] - [" + t.getName() + "] - [消息] - [" + e.getMessage() + "]");
        ConnectionPool.close();
    });
}

分析: 从日志中可以发现错误信息被我们捕获了,并且可以成功释放资源!使用UncaughtExceptionHandler,可以捕获到未知异常且记录下自定义的日志(默认抛出堆栈信息),具体在Zookeeper中就有使用过,源码为:ZookeeperThreadZooKeeperCriticalThread,有兴趣可以去看看...

- 说点什么

全文代码:https://gitee.com/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter11

个人QQ:1837307557

battcn开源群(适合新手):391619659

微信公众号:battcn(欢迎调戏)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67749.html

相关文章

  • 一起并发编程 - 利用观察者模式监听线程状态

    摘要:在前面的文章中介绍过观察者模式及并发编程的基础知识,为了让大家更好的了解观察者模式故而特意写了这篇番外概述在多线程下我们需要知道当前执行线程的状态是什么比如运行,关闭,异常等状态的通知,而且不仅仅是更新当前页面。 在前面的文章中介绍过 观察者模式 及 并发编程的基础知识,为了让大家更好的了解观察者模式故而特意写了这篇番外.. 概述 在Java多线程下,我们需要知道当前执行线程的状态是...

    Juven 评论0 收藏0
  • 一起并发编程 - 守护线程

    摘要:的作用是为其他线程的运行提供服务,比如说线程。在某些平台上,指定一个较高的参数值可能使线程在抛出之前达到较大的递归深度。参数的值与最大递归深度和并发程度之间的关系细节与平台有关。 今天研究了下Java线程基础知识,发现以前太多知识知识略略带过了,比较说Java的线程机制,在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程),以及构造器中的s...

    junnplus 评论0 收藏0
  • Java 8 并发教程:线程和执行器

    摘要:在这个示例中我们使用了一个单线程线程池的。在延迟消逝后,任务将会并发执行。这是并发系列教程的第一部分。第一部分线程和执行器第二部分同步和锁第三部分原子操作和 Java 8 并发教程:线程和执行器 原文:Java 8 Concurrency Tutorial: Threads and Executors 译者:BlankKelly 来源:Java8并发教程:Threads和Execut...

    jsdt 评论0 收藏0
  • java并发编程习11--同步器--栅栏

    摘要:考虑大量线程运行在一次计算的不同部分的情形。一旦所有的线程都到达了这个栅栏,栅栏就撤销,线程可以继续运行。那些已经在等待的线程立即中止的调用。如果在执行屏障操作过程中发生异常,则该异常将传播到当前线程中,并将置于损坏状态。 【同步器 java.util.concurrent包包含几个能帮助人们管理相互合作的线程集的类。这些机制具有为线程直间的共用集结点模式提供的‘预制功能’。如果有一个...

    desdik 评论0 收藏0
  • 一起并发编程 - sleep与wait差异

    摘要:一般差异简单来说,是一个用于线程同步的实例方法。暂停当前线程,不释放任何锁。用来线程间通信,使拥有该对象锁的线程等待直到指定时间或。执行对该对象加的同步代码块。 在JAVA的学习中,不少人会把sleep和wait搞混,认为都是做线程的等待,下面主要介绍下这俩者是什么,及了解它们之间的差异和相似之处。 一般差异 简单来说,wait()是一个用于线程同步的实例方法。因为定义在java.l...

    noONE 评论0 收藏0

发表评论

0条评论

zacklee

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<