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多线程之多线程的异常捕捉的全部内容,本文如有理解错误地方,欢迎批评改正。

相关文章

  • Spring Boot中的max-http-header-size配置方式

    Spring Boot中的max-http-header-size配置方式

    这篇文章主要介绍了Spring Boot中的max-http-header-size配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • 基于slf4j日志MDC输出格式的问题

    基于slf4j日志MDC输出格式的问题

    这篇文章主要介绍了基于slf4j日志MDC输出格式的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java微信支付之服务号支付代码示例

    Java微信支付之服务号支付代码示例

    这篇文章主要介绍了Java微信支付之服务号支付代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java调用python代码的五种方式总结

    Java调用python代码的五种方式总结

    这篇文章主要给大家介绍了关于Java调用python代码的五种方式,在Java中调用Python函数的方法有很多种,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • Java打包Jar包后使用脚本执行

    Java打包Jar包后使用脚本执行

    本文详细讲解了Java打包Jar包后使用脚本执行的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • Springcloud Nacos基本操作代码实例

    Springcloud Nacos基本操作代码实例

    这篇文章主要介绍了Springcloud Nacos基本操作代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • 通过实例解析Spring argNames属性

    通过实例解析Spring argNames属性

    这篇文章主要介绍了通过实例解析Spring argNames属性,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • mybatis 有时update语句执行无效的解决方案

    mybatis 有时update语句执行无效的解决方案

    这篇文章主要介绍了在项目里mybatis有时update语句执行无效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Spring Boot自定义配置实现IDE自动提示功能

    Spring Boot自定义配置实现IDE自动提示功能

    这篇文章主要介绍了Spring Boot自定义配置实现IDE自动提示功能,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • SpringBoot项目中使用Sharding-JDBC实现读写分离的详细步骤

    SpringBoot项目中使用Sharding-JDBC实现读写分离的详细步骤

    Sharding-JDBC是一个分布式数据库中间件,它不仅支持数据分片,还可以轻松实现数据库的读写分离,本文介绍如何在Spring Boot项目中集成Sharding-JDBC并实现读写分离的详细步骤,需要的朋友可以参考下
    2024-08-08

最新评论