线程中捕获异常

2023-10-31

总结:正常线程抛出异常时,在外部是捕捉不到的,当此类异常跑抛出时,线程就会终结,而对于主线程和其他线程完全不受影响,且完全感知不到某个线程抛出的异常(也是说完全无法catch到这个异常)。

解决方案:为线程添加未捕获异常处理器(UncaughtExceptionHandler),实现UncaughtExceptionHandler接口,重写uncaughtException方法,在方法内捕获异常。

案例:

public class ExceptionThread2 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("抛出运行时异常");
    }
}

运行结果:

该干嘛干嘛去
Exception in thread "pool-1-thread-1" java.lang.RuntimeException: 这个线程就干了这么一件事,抛出一个运行时异常
    at ExceptionThread.run(ExceptionThread.java:8)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:619)

从运行结果中,我们可以看到的是,这个异常在main线程中没有catch到,即

  System.out.println("能不能捕获到异常?");

   永远不会执行到。

        问题来了,我们如果需要捕获其线程的unchecked异常时该怎么办?Java SE5之后,我们可以通过Executor来解决这个我问题。为了解决这个问题,我们需要修改Executor产生线程的方式。Thread.UncaughtExceptionHandler是java SE5中的新接口,它允许我们在每一个Thread对象上添加一个异常处理器。(UncaughtExceptionHandler)。Thread.UncaughtExceptionHandler.uncaughtException()方法会在线程因未捕获的异常而面临死亡时被调用。

下面这个例子简单的演示了如何使用UncaughtExceptionHandler

public class ExceptionThread2 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("抛出运行时异常");
    }
}
import java.lang.Thread.UncaughtExceptionHandler;

/**
 * 用于捕获异常---捕获的是uncheckedException
 * 
 * @author February30th
 * 
 */
public class MyUnchecckedExceptionhandler implements UncaughtExceptionHandler {

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("捕获到异常:" + e);
    }

}
import java.util.concurrent.ThreadFactory;

public class HandlerThreadFactory implements ThreadFactory {

    @Override
    public Thread newThread(Runnable r) {
        System.out.println("创建一个新的线程");
        Thread t = new Thread(r);
        t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());
        System.out.println("eh121 = " + t.getUncaughtExceptionHandler());
        return t;
    }

}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ThreadExceptionTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //下面有3中方式来执行线程。
        //第1种按照普通的方式。这是能捕获到异常
        Thread t = new Thread(new ExceptionThread2());
        t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());
        t.start();
        //第2种按照现成池,直接按照thread方式,此时不能捕获到异常,为什么呢?因为在下面代码中创建了一个线程,且设置了异常处理器,
        //但是呢,在我们线程池中会重设置新的Thread对象,而这个Thread对象没有设置任何异常处理器,换句话说,我们在线程池外对线程做的
        //任何操作都是没有用的
        ExecutorService exec1 = Executors.newCachedThreadPool();
        Runnable runnable = new ExceptionThread2();
        Thread t1 = new Thread(runnable);
        t1.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());
        exec1.execute(runnable);
        
        //第3种情况一样的,也是走的线程池,但是呢是通过ThreadFactory方式,在ThreadFactory中会对线程做一些控制,可以设置异常处理器
        //此时是可以捕获异常的。
        ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
        exec.execute(new ExceptionThread2());
        
    }

}

运行结果:

创建一个新的线程
eh121 = MyUnchecckedExceptionhandler@1b8e059
run() byThread[Thread-0,5,main]
eh=MyUnchecckedExceptionhandler@1b8e059
捕获到异常:java.lang.RuntimeException: 抛出运行时异常

从上述的运行结果中可以看到,未捕获的异常是通过uncaughtException来捕获的。

按照上述的实例,我们可以按照具体的情况,逐个地设置处理器。但是如果我们知道将要在代码的所有地方都是用相同的异常处理器,那么更简单的方式是在Thread类中设置一个静态域,并将这个处理器设置为默认的未捕获异常处理器。看下面的例子:

Thread.setDefaultUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());
        ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
        exec.execute(new ExceptionThread2());

这个默认的处理器只有在线程不存在非默认的异常处理器时才会调用。 在运行时,系统会检查线程是否有属于自己的异常处理器,如果发现没有,就去检查相应的线程组是否有专有的异常处理器,如果发现也没有,再调用默认的异常处理器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线程中捕获异常 的相关文章

  • elsevier中elsarticle模板如何使用apa引用格式

    我们知道latex的默认引用 cite 是长这样的 那elsevier下面的很多期刊要求我们使用apa 美国心理学会 的引用格式 其是长这样的 方法 这个问题折磨我好久 网上说使用 usepackage apacite 包 可是我一在els

随机推荐

  • 「深度小课堂」虚拟化技术入门科普

    云计算已经成为了服务器端的潮流 通过它 我们可以有效支持弹性计算 隔离兼容等一系列的需求 计算力可以像水电一样为人们所使用 而虚拟化技术正是云计算中最重要的技术 虚拟化技术一般可以被分为两类 分别是虚拟机 VM Virtual Machin
  • sklearn的DecisionTreeClassifier的参数random_state

    刚刚使用SKLearn学习机器学习进行数据分析 分享一些概念和想法 希望可以大家一起讨论 如果理解或者表达有不准确的地方 请多多指点 不吝赐教 非常感谢 本文将继续介绍sklearn的决策树模块的其他参数 涉及到的理论知识 请转至上篇 决策
  • stm32f407zgt6的pdr_on引脚怎么接

    原文链接 https www amobbs com thread 5495105 1 1 html dsign c6460fe9 407的100脚封装没有这个PDR ON 就是VSS 在引脚分布图中为pdr on 但实际量pdr on对VS
  • 【计算机毕业设计】深度学习的驾驶行为检测

    前言 大四是整个大学期间最忙碌的时光 一边要忙着准备考研 考公 考教资或者实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几年各个学校要求的毕设项目越来越难 有不少课题是研究生级别难度的 对本科同学来说是充满挑战 为帮助大
  • 某行业CTF一道流量分析题

    今晚看了一道题 记录学习下 给了一个hacktrace pcapng 分析主要内容如下 上传两个文件 一个mouse m2s 一个mimi zip 将其导出 mimi zip中存放着secret zip和key pcapng 不过解压需要密
  • EFilm 3.1 安装文件

    国外网站上找到的 拿出来分享下 第一部分 http download csdn net detail crazpro 9696368 第二部分 http download csdn net detail crazpro 9696402 第三
  • Java:Scanner中的nextInt()方法

    文章目录 方法 验证 方法 Scanner中的nextInt 只会读取数值 剩下 n 还没有读取 并将cursor放在本行中 相当于C语言里面的scanf d i 验证 为方便描述 创建一个Scanner 对象in 注 标准输入System
  • axios的三次封装

    1 第一次封装 把项目中所有请求做的相同的事情 baseURL timeout 请求 响应式 成功或失败的提示 封装到一个文件夹里 这个文件夹通常叫做utils axios封装 通用工具函数 引入axios import axios fro
  • jdk1.8的安装和环境变量的配置最新版(超详细,保姆级教程)

    目录 一 JDK的下载和安装 1 JDK的下载 1 方式一 通过下面的链接地址直接下载jdk1 8版本 2 方式二 通过Oracle官网进行下载 2 jdk的安装 二 环境变量的配置 1 通过jdk路径配置环境变量 2 通过JAVA HOM
  • 剑指Offer53Java代码

    public class T53 public static boolean match String str String pattern if str null pattern null return false return matc
  • leetcode85 合并两个有序数组

    题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2 另有两个整数 m 和 n 分别表示 nums1 和 nums2 中的元素数目 请你 合并 nums2 到 nums1 中 使合并后的数组同样按 非递减顺序 排列 注意
  • static在c语言中是什么意思,在C语言中static有什么含义

    2019 10 10阅读 64 最主要有两点用途 让一个变量长期有效 而不管其是在什么地方被申明 比如 intfun1 staticints value 0 那么fun1不管在什么地方被调用 当函数退出后 s value最后的值将一直会被系
  • MR(MapReduce)架构

    一 什么是MR MapReduce将复杂的 运行于大规模集群上的并行计算过程高度地抽了两个函数 Map和Reduce 二 为什么使用MR 特点 1 易于编程 只关心业务逻辑 它简单的实现一些接口 就可以完成一个分布式程序 2 良好的扩展性
  • 算法面试-深度学习基础面试题整理(2023.8.29开始)

    一 无监督相关 聚类 异常检测 1 常见的距离度量方法有哪些 写一下距离计算公式 1 连续数据的距离计算 闵可夫斯基距离家族 当p 1时 为曼哈顿距离 p 2时 为欧式距离 p gt 时 就是切比雪夫距离 余弦距离 其中 A 和B是要比较的
  • Java8 consumer接口

    Java8 consumer接口 1 由来 Consumer是Java 8中的一个函数式接口 它属于java util function包 该接口定义了一个具有单个输入参数并且没有返回值的操作方法accept 2 官方常见五种示例命令和说明
  • 大数据技术与原理 概述

    大数据概述 大数据的发展历程 第一阶段 萌芽期 20世纪90年代至21世纪初 第二阶段 成熟期 21世纪前十年 第三阶段 大规模应用期 2010年以后 大数据的特点 简称4V 数据量大 数据类型多 处理速度快 价值密度低 大数据的特征 全面
  • Makefile 中gcc -lm -ldl是什么意思?

    gcc lm ldl是什么意思 包含动态链接库 到书上出现gcc lm 的选项 甚是不解 在网上查阅了一些资料 访问了一些论坛整理下 初学linux和gcc C代码调用math h中的函数有问题 如sqrt函数 若如sqrt 3 0 则可以
  • ros-sensor_msgs::PointCloud2类型消息解读

    ROS中sensor msgs PointCloud2类型消息解读 实例 header seq 2116 stamp secs 1586919439 nsecs 448866652 frame id LidarSensor1 height
  • Kubernetes系列(二)架构及特性

    在了解了k8s的发展历程之后 正式进入到学习k8s的阶段 本文主要内容是K8S的整体架构的说明和K8S一些特性的概括 架构 如下图是K8S的整体架构图 Kubernetes属于主从分布式架构 主要由Master Node和Worker No
  • 线程中捕获异常

    总结 正常线程抛出异常时 在外部是捕捉不到的 当此类异常跑抛出时 线程就会终结 而对于主线程和其他线程完全不受影响 且完全感知不到某个线程抛出的异常 也是说完全无法catch到这个异常 解决方案 为线程添加未捕获异常处理器 Uncaught