线程管理(八)在线程里处理不受控制的异常

在线程里处理不受控制的异常

Java里有2种异常:

  • 检查异常(Checked exceptions): 这些异常必须强制捕获它们或在一个方法里的throws子句中。 例如, IOException 或者ClassNotFoundException。
  • 未检查异常(Unchecked exceptions): 这些异常不用强制捕获它们。例如, NumberFormatException。

在一个线程 对象的 run() 方法里抛出一个检查异常,我们必须捕获并处理他们。因为 run() 方法不接受 throws 子句。当一个非检查异常被抛出,默认的行为是在控制台写下stack trace并退出程序。

幸运的是, Java 提供我们一种机制可以捕获和处理线程对象抛出的未检测异常来避免程序终结。

在这个指南中, 我们将用实例来学习这个机制。

准备

指南中的例子是使用Eclipse IDE 来实现的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打开并创建一个新的java项目。

怎么做呢

按照这些步骤来实现下面的例子:

1.   首先, 我们必须实现一个类来处理非检查异常。这个类必须实现 UncaughtExceptionHandler 接口并实现在接口内已声明的uncaughtException() 方法。在这里,命名此类为 ExceptionHandler  ,并让此方法里写有关于抛出异常的线程信息和异常信息,按照下面的代码:

01 public class ExceptionHandler implements UncaughtExceptionHandler
02 {
03     public void uncaughtException(Thread t, Throwable e) {
04       System.out.printf("An exception has been captured\n");
05       System.out.printf("Thread: %s\n",t.getId());
06       System.out.printf("Exception: %s: %s\n",e.getClass().getName(),e.getMessage());
07       System.out.printf("Stack Trace: \n");
08       e.printStackTrace(System.out); System.out.printf("Thread status: %s\n",t.getState());
09     }
10 }

2.   现在,实现一个类抛出非检查异常。 命名此类为Task一定要实现 Runnable 接口,实现 run() 方法并刻意出异常, 例如,尝试将 string 值转化成  int 值。

1 public class Task implements Runnable {
2 @Override
3 public void run() {
4 int numero=Integer.parseInt("TTT");
5 }
6 }

3.   现在,实现例子主类。实现 Main类和 main() 方法.

1 public class Main {
2 public static void main(String[] args) {

4.   创建 Task 对象并用线程运行它。使用 setUncaughtExceptionHandler() 方法设置非检查异常 handler 并开始执行线程。

1 Task task=new Task();
2 Thread thread=new Thread(task);
3 thread.setUncaughtExceptionHandler(new ExceptionHandler());
4 thread.start();
5 }
6 }

5.   运行例子并查看结果。

它是怎么工作的

在下面的裁图,你可以发现例子的运行结果。异常被handler捕捉,并在操控台写下了有关异常和抛出它的线程的信息。请看下图:

当在一个线程里抛出一个异常,但是这个异常没有被捕获(这肯定是非检查异常), JVM 检查线程的相关方法是否有设置一个未捕捉异常的处理者 。如果有,JVM 使用Thread 对象和 Exception 作为参数调用此方法 。

如果线程没有捕捉未捕获异常的处理者, 那么 JVM会把异常的 stack trace 写入操控台并结束任务。

更多

The Thread 类有其他相关方法可以处理未捕获的异常。静态方法 setDefaultUncaughtExceptionHandler() 为应用里的所有线程对象建立异常 handler 。

当一个未捕捉的异常在线程里被抛出,JVM会寻找此异常的3种可能潜在的处理者(handler)。

首先, 它寻找这个未捕捉的线程对象的异常handle,如我们在在这个指南中学习的。如果这个handle 不存在,那么JVM会在线程对象的ThreadGroup里寻找非捕捉异常的handler,如在处理线程组内的不受控制异常里介绍的那样。如果此方法不存在,正如我们在这个指南中学习的,那么 JVM 会寻找默认非捕捉异常handle。

如果没有一个handler存在, 那么 JVM会把异常的 stack trace 写入操控台并结束任务。

参见

  • 第一章:线程管理:在线程组里处理不受控制的异常
时间: 2024-05-22 18:38:28

线程管理(八)在线程里处理不受控制的异常的相关文章

线程管理:守护线程的创建和运行

线程管理:守护线程的创建和运行 守护线程的创建和运行Java有一种特别的线程叫做守护线程.这种线程的优先级非常低,通常在程序里没有其他线程运行时才会执行它.当守护线程是程序里唯一在运行的线程时,JVM会结束守护线程并终止程序. 根据这些特点,守护线程通常用于在同一程序里给普通线程(也叫使用者线程)提供服务.它们通常无限循环的等待服务请求或执行线程任务.它们不能做重要的任务,因为我们不知道什么时候会被分配到CPU时间片,并且只要没有其他线程在运行,它们可能随时被终止.JAVA中最典型的这种类型代表

《多核与GPU编程:工具、方法及实践》----3.8 动态线程管理与静态线程管理

3.8 动态线程管理与静态线程管理 3.2.3.1节介绍过,Qt管理一组就绪的线程池,不需要操作系统来分配和初始化新线程实体.尽管创建线程的开销较之创建进程的开销要小几个量级,但它仍然是较为耗时的,特别是当线程需要在运行时动态生成时.一个经典的粒子是监听请求和分配线程进行服务的并发Web或者数据库服务器.在这种情况下线程可以从一个空闲线程库中选取并重用,而不是为每一个请求创建一个新的线程.QThreadPool类提供的功能正是这种线程库. 本节将要介绍如何利用QThreadPool,以及如何创建

线程管理(十一)处理线程组内的不受控制异常

处理线程组内不受控制异常 对于编程语言来说,一个非常重要的事情是提供管理应用出错情况的机制.Java 语言, 作为最现代的编程语言,实现except基于异常的机制来管理出错情况,它提供很多种类来表示不同的错误.当检测到一个异常状况时,这些异常会被Java类们抛出.你也可以使用这些异常, 或者实现你自己的异常, 来管理你的类产生的错误. Java 也提供机制来捕捉和处理这些异常 .有些一定要被捕捉或者使用方法的throws句组再抛出,这些异常称为检查异常(checked exceptions).有

线程管理(四)操作线程的中断机制

操作线程的中断机制 在之前的指南里,你学习了如何中断执行线程和如何对Thread对象的中断控制.之前例子中的机制可以很容易中断的线程中使用.但是如果线程实现的是由复杂的算法分成的一些方法,或者它的方法有递归调用,那么我们可以用更好的机制来控制线程中断.为了这个Java提供了InterruptedException异常.当你检测到程序的中断并在run()方法内捕获,你可以抛这个异常. 在这个指南中, 我们将实现的线程会根据给定的名称在文件件和子文件夹里查找文件,这个将展示如何使用Interrupt

《Java程序员面试秘笈》—— 第1章 线程管理 1.1 简介

第1章 线程管理 Java 7并发编程实战手册 本章内容包括: ◆ 线程的创建和运行 ◆ 线程信息的获取和设置 ◆ 线程的中断 ◆ 线程中断的控制 ◆ 线程的休眠和恢复 ◆ 等待线程的终止 ◆ 守护线程的创建和运行 ◆ 线程中不可控异常的处理 ◆ 线程局部变量的使用 ◆ 线程的分组 ◆ 线程组中不可控异常的处理 ◆ 使用工厂类创建线程 1.1 简介 在计算机领域中,我们说的并发(Concurrency)是指一系列任务的同时运行.如果一台电脑有多个处理器或者有一个多核处理器,这个同时性(Simul

Android线程管理之ActivityThread

ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client.ActivityThread.ApplicationThread为Server)负责调度和执行activities.broadcasts和其它操作. 在Android系统中,在默认情况下,一个应用程序内的各个组件(如Activity.BroadcastReceiver.Service)都会在同一个进程(

线程管理(一)线程的创建和运行

线程的创建和运行 在这个指南中,我们将学习如何在Java程序中创建和运行线程.与每个Java语言中的元素一样,线程是对象.在Java中,我们有2个方式创建线程: 通过直接继承thread类,然后覆盖run()方法. 构建一个实现Runnable接口的类, 然后创建一个thread类对象并传递Runnable对象作为构造参数 在这个指南中,我们将使用第二种方法来制作一个简单的程序,它能创建和运行10个线程.每一个线程能计算和输出1-10以内的乘法表. 准备 指南中的例子是使用Eclipse IDE

线程管理(三)线程的中断

线程的中断 一个多个线程在执行的Java程序,只有当其全部的线程执行结束时(更具体的说,是所有非守护线程结束或者某个线程调用System.exit()方法的时候),它才会结束运行.有时,你需要为了终止程序而结束一个线程,或者当程序的用户想要取消某个Thread对象正在做的任务. Java提供中断机制来通知线程表明我们想要结束它.中断机制的特性是线程需要检查是否被中断,而且还可以决定是否响应结束的请求.所以,线程可以忽略中断请求并且继续运行. 在这个指南中, 我们将开发一个程序,它创建线程,然后在

线程管理(十)线程组

线程组 Java并发 API里有个有趣的方法是把线程分组.这个方法允许我们按线程组作为一个单位来处理.例如,你有一些线程做着同样的任务,你想控制他们,无论多少线程还在运行,他们的状态会被一个call 中断. Java 提供 ThreadGroup 类来组织线程. ThreadGroup 对象可以由 Thread 对象组成和由另外的 ThreadGroup 对象组成,生成线程树结构. 在这个指南中, 我们将开发一个简单的例子来学习 ThreadGroup 对象.我们有 10 个随机时间休眠的线程