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

相关文章

  • Java Stream的基本概念以及创建方法

    Java Stream的基本概念以及创建方法

    这篇文章主要介绍了Java Stream的基本概念以及创建方法,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-08-08
  • Spring Boot整合tk.mybatis代码实例

    Spring Boot整合tk.mybatis代码实例

    这篇文章主要介绍了Spring Boot整合tk.mybatis代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • MyBatis 动态SQL之where标签的使用

    MyBatis 动态SQL之where标签的使用

    本文主要介绍了MyBatis 动态SQL之where标签,where 标签主要用来简化 SQL 语句中的条件判断,可以自动处理 AND/OR 条件,下面就来具体介绍一下
    2024-01-01
  • JAVA得到数组中最大值和最小值的简单实例

    JAVA得到数组中最大值和最小值的简单实例

    这篇文章主要介绍了JAVA得到数组中最大值和最小值的简单实例,需要的朋友可以参考下
    2014-08-08
  • Java中异常处理之try和catch代码块的使用

    Java中异常处理之try和catch代码块的使用

    这篇文章主要介绍了Java中异常处理之try和catch代码块的使用,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • SpringBoot给类进行赋初值的四种方式

    SpringBoot给类进行赋初值的四种方式

    这篇文章主要介绍了springboot给类进行赋初值的四种方式,并通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-08-08
  • 浅谈IDEA实用的Servlet模板

    浅谈IDEA实用的Servlet模板

    今天给大家分享一下IDEA实用的Servlet模板,文中有非常详细的图文介绍及代码示例,对小伙伴们很有帮助哦,需要的朋友可以参考下
    2021-05-05
  • JavaWeb实现简单文件上传功能

    JavaWeb实现简单文件上传功能

    这篇文章主要为大家详细介绍了JavaWeb实现简单文件上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • mybatis TypeHandler注入spring的依赖方式

    mybatis TypeHandler注入spring的依赖方式

    这篇文章主要介绍了mybatis TypeHandler注入spring的依赖方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java实现把窗体隐藏到系统托盘方法

    Java实现把窗体隐藏到系统托盘方法

    这篇文章主要介绍了Java实现把窗体隐藏到系统托盘方法,本文直接给出核心功能代码,需要的朋友可以参考下
    2015-05-05

最新评论