Java多线程之多线程异常捕捉

 更新时间:2015年08月13日 11:16:53   作者:brolanda  
在java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉,通过此篇文章给大家分享Java多线程之多线程异常捕捉,需要的朋友可以参考下

  一:为什么要单独讲多线程的异常捕捉呢?

先看个例子:

public class ThreadException implements Runnable{
  @Override
  public void run() {
    throw new RuntimeException();
  }
  //现象:控制台打印出异常信息,并运行一段时间后才停止
  public static void main(String[] args){
    //就算把线程的执行语句放到try-catch块中也无济于事
    try{
      ExecutorService exec = Executors.newCachedThreadPool();
      exec.execute(new ThreadException());
    }catch(RuntimeException e){
      System.out.println("Exception has been handled!");
    }
  }
}

  在run中手动抛出了一个运行时异常,在main中启动线程,catch语句块中捕捉下异常,捕捉到打印一句话。运行结果如下图:

  发现异常被抛到了控制台,没有打印catch块中的语句。

  结论:多线程运行不能按照顺序执行过程中捕获异常的方式来处理异常,异常会被直接抛出到控制台(由于线程的本质,使得你不能捕获从线程中逃逸的异常。一旦异常逃逸出任务的run方法,它就会向外传播到控制台,除非你采用特殊的形式捕获这种异常。),这样会让你很头疼,无法捕捉到异常就无法处理异常而引发的问题。

  于是,我们一定会想如何在多线程中捕捉异常呢?

二、多线程中捕捉异常

  我们来按照下面的步骤完成这次实验:

  1.定义异常处理器

   要求,实现 Thread.UncaughtExceptionHandler的uncaughtException方法,如下:

/*
 * 第一步:定义符合线程异常处理器规范的“异常处理器”
 * 实现Thread.UncaughtExceptionHandler规范
 */
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{
  /*
   * Thread.UncaughtExceptionHandler.uncaughtException()会在线程因未捕获的异常而临近死亡时被调用
   */
  @Override
  public void uncaughtException(Thread t, Throwable e) {
    System.out.println("caught  "+e);
  }
}

  2.定义使用该异常处理器的线程工厂

/*
 * 第二步:定义线程工厂
 * 线程工厂用来将任务附着给线程,并给该线程绑定一个异常处理器
 */
class HanlderThreadFactory implements ThreadFactory{
  @Override
  public Thread newThread(Runnable r) {
    System.out.println(this+"creating new Thread");
    Thread t = new Thread(r);
    System.out.println("created "+t);
    t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());//设定线程工厂的异常处理器
    System.out.println("eh="+t.getUncaughtExceptionHandler());
    return t;
  }
}

  3.定义一个任务,让其抛出一个异常

/*
 * 第三步:我们的任务可能会抛出异常
 * 显示的抛出一个exception
 */
class ExceptionThread implements Runnable{
  @Override
  public void run() {
    Thread t = Thread.currentThread();
    System.out.println("run() by "+t);
    System.out.println("eh = "+t.getUncaughtExceptionHandler());
    throw new RuntimeException();
  }
}

  4.调用实验

/*
 * 第四步:使用线程工厂创建线程池,并调用其execute方法
 */
public class ThreadExceptionUncaughtExceptionHandler{
  public static void main(String[] args){
    ExecutorService exec = Executors.newCachedThreadPool(new HanlderThreadFactory());
    exec.execute(new ExceptionThread());
  }
}

  运行结果如下图:

三、结论

  在java中要捕捉多线程产生的异常,需要自定义异常处理器,并设定到对应的线程工厂中(即第一步和第二步)。

四、拓展

  如果你知道将要在代码中处处使用相同的异常处理器,那么更简单的方式是在Thread类中设置一个静态域,并将这个处理器设置为默认的未捕获处理器。

这个处理器只有在不存在线程专有的未捕获异常处理器的情况下才会被调用。

public static void main(String[] args){
    Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
    ExecutorService exec =Executors.newCachedThreadPool();
    exec.execute(new ExceptionThread());
}

以上就是本文针对Java多线程之多线程的异常捕捉的全部内容,本文如有理解错误地方,欢迎批评改正。

相关文章

  • struts2的流程和一系列相关知识代码解析

    struts2的流程和一系列相关知识代码解析

    这篇文章主要介绍了struts2的流程和一系列相关知识代码解析,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • 解决Spring Security 用户帐号已被锁定问题

    解决Spring Security 用户帐号已被锁定问题

    这篇文章主要介绍了解决Spring Security 用户帐号已被锁定问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • java类的组成结构详解

    java类的组成结构详解

    大家好,本篇文章主要讲的是java类的组成结构详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • 浅谈hibernate中多表映射关系配置

    浅谈hibernate中多表映射关系配置

    下面小编就为大家带来一篇浅谈hibernate中多表映射关系配置。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • springboot实现excel表格导出几种常见方法

    springboot实现excel表格导出几种常见方法

    在日常的开发中避免不了操作Excel,下面这篇文章主要给大家介绍了关于springboot实现excel表格导出的几种常见方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • 详解spring boot实现多数据源代码实战

    详解spring boot实现多数据源代码实战

    本篇文章主要介绍了详解spring boot实现多数据源代码实战,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Java封装数组之动态数组实现方法详解

    Java封装数组之动态数组实现方法详解

    这篇文章主要介绍了Java封装数组之动态数组实现方法,结合实例形式详细分析了java动态数组的实现原理、操作步骤与相关注意事项,需要的朋友可以参考下
    2020-03-03
  • java获取客服端信息的方法(系统,浏览器等)

    java获取客服端信息的方法(系统,浏览器等)

    下面小编就为大家带来一篇java获取客服端信息的方法(系统,浏览器等)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • 详解lambda表达式foreach性能分析

    详解lambda表达式foreach性能分析

    这篇文章主要介绍了详解lambda表达式foreach性能分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Java Http多次请求复用同一连接示例详解

    Java Http多次请求复用同一连接示例详解

    这篇文章主要为大家介绍了Java Http多次请求复用同一连接示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10

最新评论