《Java程序员面试秘笈》—— 1.12 线程组中不可控异常的处理

简介: 提供应用程序中对错误情景的管理,是编程语言很重要的一面。和几乎所有的现代编程语言一样,Java语言也实现了通过异常管理机制来处理错误情景,它提供了很多类来表示不同的错误。当错误情景发生时,Java类将抛出这些异常。你可以使用这些异常,或者实现自己的异常,来管理类中的错误。

本节书摘来异步社区《Java 7并发编程实战手册》一书中的第1章,第1.12节,作者:【西】Javier Fernández González,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.12 线程组中不可控异常的处理

提供应用程序中对错误情景的管理,是编程语言很重要的一面。和几乎所有的现代编程语言一样,Java语言也实现了通过异常管理机制来处理错误情景,它提供了很多类来表示不同的错误。当错误情景发生时,Java类将抛出这些异常。你可以使用这些异常,或者实现自己的异常,来管理类中的错误。

Java也提供了捕获和处理这些异常的机制。有的异常必须被捕获,或者必须使用方法的throws声明再次抛出,这类异常叫做非运行时异常。还有一类异常叫做运行时异常,它们不需要被捕获或者声明抛出。

在本章1.5节中,我们学习了如何在线程对象中处理非捕获异常。

另一种可行的做法是,建立一个方法来捕获线程组中的任何线程对象抛出的非捕获异常。

本节中,我们将通过范例学习这种异常处理的方法。

准备工作
本节的范例是在Eclipse IDE里完成的。无论你使用Eclipse还是其他的IDE(比如NetBeans),都可以打开这个IDE并且创建一个新的Java工程。

范例实现
按照接下来的步骤实现本节的范例。

1.创建一个MyThreadGroup类,并继承ThreadGroup。必须声明带参数的构造器,因为ThreadGroup没有默认的不带参数的构造器。

public class MyThreadGroup extends ThreadGroup {
  public MyThreadGroup(String name) {
    super(name);
}```
2.覆盖uncaughtException()方法。当线程组中的任何线程对象抛出异常的时候,这个方法就会被调用。在这里,这个方法将打印异常信息和抛出异常的线程代码到控制台,还将中断线程组中的其他线程。

@Override
public void uncaughtException(Thread t, Throwable e) {

System.out.printf("The thread %s has thrown an Exception\n",t. getId());

e.printStackTrace(System.out);
System.out.printf("Terminating the rest of the Threadsn");
interrupt();
}`
3.创建一个Task类,它实现了Runnable接口。
``
public class Task implements Runnable {``
4.实现run()方法。在这个方法里,我们要触发AritmethicException异常。为了达到目标,我们用1000除以一个随机数,当随机数生成器生成0,异常将被抛出。

@Override
public void run() {
  int result;
  Random random=new Random(Thread.currentThread().getId());
  while (true) {
    result=1000/((int)(random.nextDouble()*1000));
    System.out.printf("%s : %d\n",Thread.currentThread(). getId(),result);
      if (Thread.currentThread().isInterrupted()) {
       System.out.printf("%d : Interrupted\n",Thread. currentThread().getId());
        return;
       }
   }
}```
5.实现这个范例的主程序,并且实现main()方法。

public class Main {
public static void main(String[] args) {`
6.创建一个MyThreadGroup线程组类对象。
``
MyThreadGroup threadGroup=new MyThreadGroup("MyThreadGroup");``
7.创建一个Task类对象。
``
Task task=new Task();``
8.用刚创建的两个对象作为传入参数,创建两个线程对象。

for (int i=0; i<2; i++){
  Thread t=new Thread(threadGroup,task);
  t.start();
}```
9.运行范例并查看运行结果。

工作原理
当运行范例的时候,你会看到当一个线程对象抛出了异常,其余的线程对象都被中断。

当线程抛出非捕获异常时,JVM将为这个异常寻找3种可能的处理器。

首先,寻找抛出这个异常的线程的非捕获异常处理器,参见1.9节。如果这个处理器不存在,JVM继续查找这个线程所在的线程组的非捕获异常处理器,这也是本节学习的知识。如果也不存在,JVM将寻找默认的非捕获异常处理器,参见1.9节。

如果这些处理器都不存在,JVM将把堆栈中异常信息打印到控制台,并且退出这个程序。
相关文章
|
5天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
18 2
|
9天前
|
存储 缓存 Java
java线程内存模型底层实现原理
java线程内存模型底层实现原理
java线程内存模型底层实现原理
|
7天前
|
Java 编译器 索引
|
7天前
|
IDE Java 开发工具
java自定义异常20
java自定义异常20
15 3
|
7天前
|
IDE Java 开发工具
java捕获异常19
java捕获异常19
12 2
|
7天前
|
Java 调度
Java-Thread多线程的使用
这篇文章介绍了Java中Thread类多线程的创建、使用、生命周期、状态以及线程同步和死锁的概念和处理方法。
Java-Thread多线程的使用
|
10天前
|
Java 调度 开发者
Java中的多线程编程:从基础到实践
本文旨在深入探讨Java多线程编程的核心概念和实际应用,通过浅显易懂的语言解释多线程的基本原理,并结合实例展示如何在Java中创建、控制和管理线程。我们将从简单的线程创建开始,逐步深入到线程同步、通信以及死锁问题的解决方案,最终通过具体的代码示例来加深理解。无论您是Java初学者还是希望提升多线程编程技能的开发者,本文都将为您提供有价值的见解和实用的技巧。
15 2
|
5天前
|
Java 数据中心 微服务
Java高级知识:线程池隔离与信号量隔离的实战应用
在Java并发编程中,线程池隔离与信号量隔离是两种常用的资源隔离技术,它们在提高系统稳定性、防止系统过载方面发挥着重要作用。
6 0
|
7天前
|
Java 数据处理 调度
Java中的多线程编程:从基础到实践
本文深入探讨了Java中多线程编程的基本概念、实现方式及其在实际项目中的应用。首先,我们将了解什么是线程以及为何需要多线程编程。接着,文章将详细介绍如何在Java中创建和管理线程,包括继承Thread类、实现Runnable接口以及使用Executor框架等方法。此外,我们还将讨论线程同步和通信的问题,如互斥锁、信号量、条件变量等。最后,通过具体的示例展示了如何在实际项目中有效地利用多线程提高程序的性能和响应能力。
|
8天前
|
安全 算法 Java
Java中的多线程编程:从基础到高级应用
本文深入探讨了Java中的多线程编程,从最基础的概念入手,逐步引导读者了解并掌握多线程开发的核心技术。无论是初学者还是有一定经验的开发者,都能从中获益。通过实例和代码示例,本文详细讲解了线程的创建与管理、同步与锁机制、线程间通信以及高级并发工具等主题。此外,还讨论了多线程编程中常见的问题及其解决方案,帮助读者编写出高效、安全的多线程应用程序。
下一篇
无影云桌面