Java多线程异常处理

2023-11-14

一. 线程中出现异常的处理

1. 线程出现异常的默认行为

当单线程中初出现异常时,我们可在该线程run()方法的catch语句中进行处理,当有多个线程中出现异常时,我们就得在每个线程run()方法的catch语句中进行处理,这样会造成代码严重冗余。我们可以使用setDefaultUncaoughtExceptionHandler()和方法setUncaughtExceptionHandler()方法来集中处理线程的异常。

public class Main{
    public static void main(String[] args) {
        MyThread t=new MyThread();
        t.start();
    }
}
class  MyThread extends Thread{
   @Override
    public void run(){ 
      String username=null;
       System.out.println(username.hashCode());
   }
}

在这里插入图片描述
如上面的程序,程序运行后,控制台输出空指针异常。在java的多线程技术中,我们可以对多线程中的异常进行捕获,使用的是UncaughtExceptionHandler接口。从而对异常进行有效处理。当线程出现异常而终止时,JVM虚拟机捕获到此情况,并自动调用UncaughtExceptionHandler接口中的void uncaughtException(Thread t,Throwable e)方法来处理异常,使对多个线程的异常处理更集中。

2. setUncaoughtExceptionHandler()方法处理异常

public class Main{
    public static void main(String[] args) {
        MyThread t=new MyThread();
        t.setName("线程t");
        t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("线程:"+t.getName()+"出现了异常");
            }
        });
        t.start();
        MyThread t2=new MyThread();
        t2.setName("线程t2");
        t2.start();
    }
}
class  MyThread extends Thread{
   @Override
    public void run(){
      String username=null;
       System.out.println(username.hashCode());
   }
}

setUncaughtExceptionHandler方法的作用是对指定的线程对象设置默认的异常处理器。在Thread类中,我们还可以使用setDefaultUncaoughtExceptionHandler方法对所有的线程设置异常处理器

3. setDefaultUncaoughtExceptionHandler()方法进行异常处理

public class Main{
    public static void main(String[] args) {
        MyThread t=new MyThread();
        t.setName("线程t");
        MyThread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("线程:"+t.getName()+"出现了异常");
                e.printStackTrace();
            }
        });
        t.start();
        MyThread t2=new MyThread();
        t2.setName("线程t2");
        t2.start();
    }
}
class  MyThread extends Thread{
   @Override
    public void run(){
      String username=null;
       System.out.println(username.hashCode());
   }
}

在这里插入图片描述

可以对所有的线程都生效了

二. 线程组内出现异常

Java中的线程组(ThreadGroup)用于将一组线程组织在一起,并提供一些管理和操作的功能。然而,线程组在现代的Java编程中已经不常使用,并且在Java 9中已被标记为过时(deprecated)。尽管如此,我们可以描述一下线程组可能出现的异常情况和行为。以下是一些可能与线程组相关的异常:

  • IllegalThreadStateException(非法线程状态异常):当尝试将一个线程添加到已经销毁的线程组或一个线程组已经被终止时,可能会抛出此异常。

  • SecurityException(安全异常):在某些安全受限的环境中,如果没有足够的权限创建或修改线程组,可能会抛出此异常。

  • NullPointerException(空指针异常):在某些情况下,尝试对一个空的线程组对象进行操作(如添加线程、设置线程组名称等)可能会导致此异常。

需要注意的是,由于线程组在现代Java编程中已经不常用,因此在实际开发中可能很少会遇到与线程组相关的异常。为了更好地管理和组织线程,推荐使用更高级别的并发工具,如线程池(ThreadPoolExecutor)和并发集合(ConcurrentHashMap、ConcurrentLinkedQueue等)。

public class Main{
    public static void main(String[] args) {
        ThreadGroup group=new ThreadGroup("线程组");
        MyThread[] myThreads=new MyThread[10];
        for (int i = 0; i < myThreads.length; i++) {
            myThreads[i]=new MyThread(group,"线程"+(i+1),"1");
            myThreads[i].start();
        }
        MyThread newT=new MyThread(group,"报错线程","aasdfsdf");
        newT.start();
    }
}
class  MyThread extends Thread{
    private String num;
    public MyThread(ThreadGroup group,String name,String num){
        super(group,name);
        this.num=num;
    }
   @Override
    public void run(){
      int minINt=Integer.parseInt(num);
      while(true){
          System.out.println("死循环中:"+Thread.currentThread().getName());
          try {
              Thread.sleep(1000);
          } catch (InterruptedException e) {
              throw new RuntimeException(e);
          }
      }
   }
}

在这里插入图片描述

程序运行后其中一个线程出现了异常,而其它线程一直以死循环的方式持续打印结果。从运行结果来看,默认情况下线程组中的一个线程出现异常后不会影响其他线程的运行。见下面代码:

public class Main{
    public static void main(String[] args) {
        MyThreadGroup group=new MyThreadGroup("线程组");
        MyThread[] myThreads=new MyThread[10];
        for (int i = 0; i < myThreads.length; i++) {
            myThreads[i]=new MyThread(group,"线程"+(i+1),"1");
            myThreads[i].start();
        }
        MyThread newT=new MyThread(group,"报错线程","aasdfsdf");
        newT.start();
    }
}
class  MyThread extends Thread{
    private String num;
    public MyThread(ThreadGroup group,String name,String num){
        super(group,name);
        this.num=num;
    }
   @Override
    public void run(){
      int minINt=Integer.parseInt(num);
      while(this.isInterrupted()==false){
          System.out.println("死循环中:"+Thread.currentThread().getName());
      }
   }
}
class MyThreadGroup extends ThreadGroup{
    public MyThreadGroup(String name){
        super(name);
    }
    @Override
    public void uncaughtException(Thread t,Throwable e){
        super.uncaughtException(t,e);
        this.interrupt();
    }
}

在这里插入图片描述

可见发现所有的线程都停止了。这里使用自定义的线程组,并重写了uncaughtException,当线程出现异常时调用interrupt方法,终止所有线程。

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

Java多线程异常处理 的相关文章

随机推荐

  • 计算机主板上的fan,通用解决方案:计算机主板上的CPU_FAN,SYS_FAN,CHA_FAN,CPU_OPT接口知识...

    在组装计算机的过程中 尽管安装过程很简单 但经常会遇到接线问题 用户经常错误地将CPU散热器的电源线插入SYS FAN 尽管风扇可以旋转 但是在引导时可能会出现F1错误 CPU Fan Error 这也会导致CPU散热器无法智能调节速度 让
  • javafx开发- ImageView标签设置图片不显示

    图片不显示的原因没找到 但是找到了解决办法 嘿嘿 解决问题代码如下
  • flutter之Provider(一)

    网上有不少介绍Provider的文章 但是感觉大部分对于初学者而言不够友好 很多在文章开始就写了大片的代码或者是一通的状态管理的介绍 但是实际上根本不需要那么复杂 本篇文章当然也会简单的介绍Provider的使用 但是我们更多还是通俗的介绍
  • 新手教程!设置PDF文件的页面大小

    设置文档的页面大小是办公一族经常遇到的一种操作 如果是word文档 那简直就是so easy 但在日常工作中 我们偶尔会遇到PDF格式的文件 由于对它不熟悉 想要对PDF文档的页面大小进行修改 又该如何操作呢 这时我们就需要借助一款非常专业
  • 客户价值预测:线性回归模型与诊断(概念)

    客户生命周期可分为四个阶段 潜在客户阶段 响应客户阶段 既得客户阶段 流失客户阶段 本章整体是一个客户价值预测的案例 背景是某信用卡公司在地推活动之后 获取了大量客户的信用卡申请信息 其中一个部分客户顺利开卡 并且有月消费记录 而另外一部分
  • C语言结构体应用-通讯录

    这里写目录标题 总体介绍 一 数据的定义及数据初始化 二 增加联系人 三 删除联系人 四 修改某个联系人 五 显示所有联系人 六 删除所有联系人 七 按名字首字母排序联系人 八 查找联系人 九 代码展示 总体介绍 本文主要介绍一个结构体的应
  • vue 点击事件失效

    点击事件失效的情况 总共有三种 1 没有点到那个元素 比如说div gt span 事件绑定在div上 但是它可能点来点去是在span标签上面 这种情况 把 click点击事件绑定到span上测试一下就好了 如果是被覆盖了 加个这个 sto
  • error while loading shared libraries: libcublasLt.so.11 解决方法

    在运行cuda程序的时候 有时候会遇到此类错误 error while loading shared libraries libcublasLt so 11 问题是两个 确实没有此类库文件 有此库文件 不过没有放在正确的地方 针对第一类 如
  • Java实现将JSON文件导出到Excel

    文章目录 一 运行环境 二 需求描述 三 实现思路 四 实现代码 一 运行环境 windows10 IDEA 2022 JDK 8 Maven 3 8 6 Apache POI 5 fastjson2 二 需求描述 写一个功能 任意json
  • 利用Vulnhub复现漏洞 - Adobe ColdFusion 反序列化漏洞(CVE-2017-3066)

    Adobe ColdFusion 反序列化漏洞 CVE 2017 3066 Vulnhub官方复现教程 漏洞原理 复现漏洞 启动环境 漏洞复现 生成POC 发送POC 发送POC内容 检验POC 进入容器 通过DockerID进入容器 查看
  • 软工实践2019——第二次作业评分

    第二次作业评分 第二次作业原文 写在前面的话 看了大家陆续提交的第一次作业 感慨良多 初心 勇气和信心 回顾初心 回想自己当初为什么报这个专业 不知你们是否看过电影 无问西东 其中有一句台词 如果提前了解了你们要面对的人生 不知你们是否还会
  • VirtualBox中安装Android-x86详解

    1 下载安装VirtualBox 官网 http www virtualbox org wiki Downloads 2 下载Android x86 官网 http www android x86 org download 这里我们下载5
  • 19. 第三方库的管理和虚拟环境

    Hi 大家好 我是茶桁 在我们之前的课程中 讲解了数据 函数 类 模块以及包 这些基本上已经构成了Python的全部了 那么 我们在学习Python的包之后 有没有思考过 既然Python有内置模块 我们也可以自己写一些模块来使用 那一定有
  • 3D游戏设计作业10:AR/MR 技术

    AR MR 技术 游戏截图 1 作业要求 1 图片识别与建模 2 虚拟按键小游戏 2 设计思路 1 首先是要安装Vuforia 这里直接在file build settings player settings里勾选Vuforia Augme
  • 【漏洞复现】CVE-2021-32682 elFinder ZIP 参数与任意命令注入

    1 Vulhub启动环境 2 查看端口号 3 输入网址 ip 8080 打开网页 4 先创建一个普通的文本文件1 txt 5 然后右键这个文件 对其进行打包 打包后的文件命名为2 zip 并同时进行抓包 获取1 txt的base64编码 6
  • 成员变量与局部变量

    一 成员变量 在类中定义 用来描述对象将要有什么 二 局部变量 在类的方法中定义 在方法中临时保存数据 三 成员变量和局部变量的区别 1 作用域不同 局部变量的作用域仅限于定义它的方法 成员变量的作用域在整个类内部都是可见的 2 初始值不同
  • 【总结】爬虫流程

    爬虫流程 根据所需数据确定爬虫网页 首先考虑resquests 需要提前导入 1 若是文本数据 用response text 2 若是下载视频 图片 音频 用response content 3 若是json接口 用response jso
  • CSS整体界面设计

  • RBAC简介

    RBAC BAC基于角色的访问控制 RBAC认为权限授权的过程可以抽象地概括为 Who是否可以对What进行How的访问操作 RBAC简介 基于角色的权限访问控制模型 在RBAC模型里面 有3个基础组成部分 分别是 用户 角色和权限 RBA
  • Java多线程异常处理

    文章目录 一 线程中出现异常的处理 1 线程出现异常的默认行为 2 setUncaoughtExceptionHandler 方法处理异常 3 setDefaultUncaoughtExceptionHandler 方法进行异常处理 二 线