关于java:并发王者课青铜9防患未然如何处理线程中的异常

9次阅读

共计 3738 个字符,预计需要花费 10 分钟才能阅读完成。

欢送来到《并发王者课》,本文是该系列文章中的 第 9 篇

在本篇文章中,我将为你介绍线程中异样的解决形式以及 uncaughtExceptionHandler 用法

一、新线程中的异样去哪了

应用程序在执行过程中,难免会呈现各种意外谬误,如果咱们没有对谬误进行捕捉解决,会间接影响利用的运行后果,甚至导致利用解体。而在利用异样解决中,多线程的异样解决是比拟重要又容易犯错的中央。

接下来,咱们通过一段代码模仿一种常见的多线程异样解决形式。

在上面的代码中,咱们在主线程中创立了新线程 nezhaThread,并冀望在主线程中捕捉新线程中抛出的异样:

 public static void main(String[] args) {Thread neZhaThread = new Thread() {public void run() {throw new RuntimeException("我是哪吒,我被围攻了!");
            }
        };
        // 尝试捕捉线程抛出的异样
        try {neZhaThread.start();
        } catch (Exception e) {System.out.println("接管英雄异样:" + e.getMessage());
        }
    }

运行后果如下:

Exception in thread "Thread-0" java.lang.RuntimeException: 我是哪吒,我被围攻了!at cn.tao.king.juc.execises1.ExceptionDemo$1.run(ExceptionDemo.java:7)

Process finished with exit code 0

对于多线程老手来说,可能并不能间接看出其中的不合理。然而,从运行的后果中能够看到,没有输入“接管英雄异样”关键字。也就是说,主线程并未能捕捉新线程的异样。 那这是为什么呢?

了解这一景象,首先要从线程的实质登程。在 Java 中,每个线程所运行的都是独立运行的代码片段,如果咱们没有被动提供线程间通信和合作的机制,那么它们彼此之间是隔离的。

换句话说,每个线程都要在本人的闭环内实现全副的工作解决,包含对异样的解决,如果出错了但你没有被动解决异样,那么它们会依照既定的流程自我了结

二、多线程中的异样解决形式

1. 从主线程看异样的解决

为了了解多线程中的错误处理形式,咱们先看常见的主线程是如何处理错误的,毕竟绝对于多线程,繁多的主线程更容易让人了解。

 public static void main(String[] args) {throw new NullPointerException();
    }

很显著,下面这段代码将会抛出上面错误信息:

Exception in thread "main" java.lang.NullPointerException
    at cn.tao.king.juc.execises1.ExceptionDemo.main(ExceptionDemo.java:21)

对于相似于空指针谬误的堆栈信息,置信你肯定并不生疏。在主线程中解决这样的异样很简略,通过编写 trycatch 代码块即可。但其实,除了这种形式外,咱们还能够通过定义 uncaughtExceptionHandler 来解决主线程中的异样。

 public static void main(String[] args) {Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
        throw new NullPointerException();}

    // 自定义错误处理
    static class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {public void uncaughtException(Thread t, Throwable e) {System.out.println("出错了!线程名:" + t.getName() + ",错误信息:" + e.getMessage());
        }
    }

输入后果如下:

出错了!线程名:main,错误信息:null

Process finished with exit code 1

你看,咱们曾经地捕捉了异样。然而,你可能会纳闷为什么 Thread.UncaughtExceptionHandler 能够自定义错误处理?说到这,就不得不提 Java 中的异样解决形式,如下图所示:

在 Java 中,咱们常常能够看到空指针那样的谬误的堆栈信息,然而这个堆栈实则是线程在出错的状况下 “不得已” 才输入来的。从图中咱们能够看到:

  • 当线程出错时,首先会查看以后线程是否指定了谬误处理器;
  • 如果以后线程没有指定谬误处理器,则持续查看其所在的线程组是否指定(留神,后面咱们曾经说过,每个线程都是有线程组的);
  • 如果以后线程的线程组也没有指定,则持续查看其父线程是否指定;
  • 如果父线程同样没有指定谬误处理器,则最初查看默认解决是否设置;
  • 如果默认处理器也没有设置,那么将不得不输入谬误的堆栈信息

2. 多线程间的异样解决

不要遗记,主线程也是线程 ,所以当你了解了主线程的错误处理形式后,你也就了解了子线程中的异样解决形式,它们和主线程是雷同的。在主线程中,咱们能够通过Thread.setDefaultUncaughtExceptionHandler 来设置自定义异样处理器。而在新的子线程中,则能够通过 线程对象 间接指定异样处理器,比方咱们给后面的 neZhaThread 线程设置异样处理器:

neZhaThread.setName("哪吒");
neZhaThread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

那么,设置处理器后的线程异样信息则输入如下:

出错了!线程名:哪吒,错误信息:我是哪吒,我被围攻了!Process finished with exit code 0

你看,通过定义uncaughtExceptionHandler,咱们曾经捕捉并解决了新线程抛出的异样。

3. 了解 UncaughtExceptionHandler

从下面的代码中,置信你曾经直观地了解 UncaughtExceptionHandler 用法。在 Java 中,UncaughtExceptionHandler 用于解决线程忽然异样终止的状况 。当线程因某种原因抛出未解决的异样时,JVM 虚拟机将会通过线程中的getUncaughtExceptionHandler 查问该线程的谬误处理器,并将该线程和异样信息作为参数传递过来。如果该线程没有指定谬误处理器,将会依照上图所示的流程持续查找。

三、定义 uncaughtExceptionHandler 的三个层面

1. 定义默认异样处理器

默认的谬误处理器能够作为线程异样的兜底处理器,在线程和线程组未指定异样处理器时,能够应用默认的异样处理器。

 Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

2. 自定义特定的异样处理器

如果某个线程须要特定的处理器时,通过线程对象指定异样处理器是个很不错的抉择。当然,这种异样处理器不能够与其余线程共享。

neZhaThread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

3. 继承 ThreadGroup

通过继承 ThreadGroup 并覆写 uncaughtException 能够重设以后线程组的异样处理器逻辑。不过要留神的是,覆写线程组的行为并不常见,应用时须要谨慎。

public class MyThreadGroupDemo  extends ThreadGroup{public MyThreadGroupDemo(String name) {super(name);
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // 在这里重写线程组的异样解决逻辑
        System.out.println("出错了!线程名:" + t.getName() + ",错误信息:" + e.getMessage());
    }
}

小结

以上就是对于线程异样解决的全部内容,在本文中咱们介绍了多线程异样的解决形式以及 uncaughtExceptionHandler 的用法。对于多线程的异样解决应该记住:

  • 线程外部的异样应尽可能在其外部解决
  • 如果主线程须要捕捉子线程异样,不能够应用trycatch,而是要应用uncaughtExceptionHandler。当然,曾经在子线程外部捕捉的异样,主线程将无奈捕捉。

注释到此结束,祝贺你又上了一颗星✨

夫子的试炼

  • 编写代码理解并体验 uncaughtExceptionHandler 用法。

延长浏览

  • 《并发王者课》纲要与更新进度总览

对于作者

关注公众号【庸人技术笑谈】,获取及时文章更新。记录平凡人的技术故事,分享有品质(尽量)的技术文章,偶然也聊聊生存和现实。不贩卖焦虑,不做题目党。

如果本文对你有帮忙,欢送 点赞 关注 监督 ,咱们一起 从青铜到王者

正文完
 0