Java多线程异常处理

文章目录

  • 一. 线程中出现异常的处理
    • 1. 线程出现异常的默认行为
    • 2. setUncaoughtExceptionHandler()方法处理异常
    • 3. setDefaultUncaoughtExceptionHandler()方法进行异常处理
  • 二. 线程组内出现异常

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

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方法,终止所有线程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/21879.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LOTO示波器如何测试阻抗的频响曲线

LOTO示波器如何测试阻抗的频响曲线 模块的输入输出端口&#xff0c;在电路分析上&#xff0c;一般简单表征为电阻来进行计算和分析。但多数情况下&#xff0c;这些端口并不是纯电阻的特性&#xff0c;更精确一些&#xff0c;它可能是电阻电容以及电感的组合&#xff0c;表现为非…

ChatGPT 聊天接口API 使用

一、准备工作 1.准备 OPENAI_ACCESS_TOKEN 2.准备好PostMan 软件 二、测试交流Demo 本次使用POSTMAN工具进行快速测试&#xff0c;旨在通过ChatGPT API实现有效的上下文流。在测试过程中&#xff0c;我们发现了三个问题&#xff1a;    1.如果您想要进行具有上下文的交流&…

从供应链协同角度挖掘数字化应用场景

企业在数字化转型的过程中&#xff0c;供应链的数字化转型是绕不开的话题。供应链的数字化转型&#xff0c;是借助数字化技术赋能企业和供应链从业人员&#xff0c;驱动业务向更加高效智能的方向发展。越来越多的企业意识到需要依靠新技术&#xff0c;也往往非常强调新技术的应…

为什么我们应该选择Renderbus瑞云渲染进行 EEVEE 渲染?

在某些情况下&#xff0c;用户需要高精度、快速的渲染&#xff0c;而 EEVEE的诞生就是为了满足这种需求。Eevee&#xff08;Extra Easy Virtual Environment Engine&#xff09;是 Blender 最新的内部渲染引擎&#xff0c;由用于 Epic Games 开发的虚幻引擎的相同代码提供支持…

openldap介绍以及使用

参考文献&#xff1a;openldap介绍和使用 基本概念 官网&#xff1a;https://www.openldap.org 官方文档&#xff1a;https://www.openldap.org/doc LDAP是一个开放的&#xff0c;中立的&#xff0c;工业标准的应用协议&#xff0c;通过IP协议提供访问控制和维护分布式信息的…

【Linux】进程信号“疑问?坤叫算信号吗?“

鸡叫当然也算信号啦~ 文章目录 前言一、认识信号量二、信号的产生 1.调用系统函数向进程发信号2.由软件条件产生信号3.硬件异常产生信号总结 前言 信号在我们生活中很常见&#xff0c;下面我们举一举生活中信号的例子&#xff1a; 你在网上买了很多件商品&#xff0c;再等待不…

统计一个数的二进制中1的个数(三种方法)

那么好了好了&#xff0c;宝子们&#xff0c;今天给大家分享一篇经典例题的三种实现方法&#xff0c;来吧&#xff0c;开始整活&#xff01;⛳️ 一、基础法 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int number_of_one(int n) {int count 0;while(n){if…

VTKmimics Calculate Parts

前言&#xff1a;本博文主要研究mimics中Calculate Parts所采用的方法以及VTK中三维重建的方法&#xff0c;希望对各位小伙伴有所帮助&#xff0c;谢谢&#xff01; mimics-Calculate parts - Interpolation Gray Interpolation 灰度值插值是一种真正的3D插值&#xff0c;它考…

宝塔面板快速搭建贪吃蛇小游戏web网站 - 无需云服务器,网站发布上线

文章目录 前言视频教程1. 环境安装2. 安装cpolar内网穿透3. 内网穿透4. 固定http地址5. 配置二级子域名6. 创建一个测试页面&#x1f34e;总结 转载自远程内网穿透的文章&#xff1a;Linux使用宝塔面板搭建网站&#xff0c;并内网穿透实现公网访问 前言 宝塔面板作为简单好用的…

RoyalScope-总线工作状况和信号质量“体检”

海量存储、洞悉细微 无间断连续采样、波形和报文记录 内置100MHz示波器&#xff0c;采样率高达100MS/s&#xff0c;精确查看、分析和统计信号波形细节。 无间断连续采样总线上信号&#xff0c;全部无遗漏的解析成报文(包括数据帧、遥控帧、过载帧、错误帧、帧间隔和错误报文)和…

Vue3-黑马(十四)

目录&#xff1a; &#xff08;1&#xff09;vue3-进阶-router-令牌-前端路由 &#xff08;2&#xff09;vue3-进阶-router-令牌-前端路由 &#xff08;3&#xff09;vue3-进阶-pinia1 &#xff08;4&#xff09;vue3-进阶-pinia2 &#xff08;1&#xff09;vue3-进阶-rout…

ARM学习笔记_2 模式,寄存器,流水线

ARM arm体积小功耗低性能高&#xff0c;支持thumb ARM双指令集&#xff0c;兼容8/16位器件&#xff1b;大量使用寄存器&#xff0c;指令定长&#xff0c;寻址简单。 ARM是32位架构&#xff0c;Word 32bit&#xff0c; half Word 16bit. 模式 用户模式是用户程序的模式&#…

GPT-2(Transformer Decoder)的TensorFlow实现(附源码)

文章目录 一、GPT2实现步骤二、源码 一、GPT2实现步骤 机器学习模型的开发实现步骤一般都包含以下几个部分&#xff1a;   1. 遵照模型的网络架构&#xff0c;实现每一层&#xff08;Layer/Block&#xff09;的函数&#xff1b;   2. 将第1步中的函数组合在一起&#xff0c…

Typecho搭建和美化

概述 Typecho是一款轻量级的开源PHP博客系统&#xff0c;它简单易用&#xff0c;界面整洁&#xff0c;性能高效&#xff0c;主题、插件众多。我使用的是腾讯云轻量服务器&#xff0c;Typecho的应用模版&#xff0c;一键安装环境。构建自己的博客网站&#xff0c;记录生活、分享…

容器简单介绍

目录 一、容器简介​编辑 二、容器和虚拟化技术差异 三、容器基本概念 四、容器技术对企业优势 五、容器的工具 一、容器简介 docker只是容器工具&#xff0c;真正容器技术是LXC &#xff08;linux container&#xff09; 二、容器和虚拟化技术差异 虚拟机模式&#xff…

AI人工智能逻辑回归的原理、优缺点、应用场景和实现方法

逻辑回归&#xff08;Logistic Regression&#xff09;是一种常见的机器学习算法&#xff0c;它被广泛应用于分类问题。在人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;领域中&#xff0c;逻辑回归是一种简单而有效的算法&#xff0c;可以用于许…

vue+elementui+nodejs高校校园在线打印预约系统

在线提交文档进行打印 首页简单介绍系统 语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;VScode 顶部或主页按钮转到打印 用户可以登录 查看历史打印记录 用户分学生和非学生 学生可以享有优惠…

【C#】GridControl增加选择列(不用二次点击)

系列文章 【C#】单号生成器&#xff08;编号规则、固定字符、流水号、产生业务单号&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器&#xff08;开始日期、结束日期&#xff09; 本文链接&#xff1a;h…

黑马Redis原理篇

黑马Redis原理篇 1、数据结构1.1、动态字符串SDS1.2、IntSet1.3、Dict1.4、ZipList1.5、QuickList1.6、SkipList1.7、RedisObject1.8、五种数据结构1. String&#xff08;小EMBSTR,大RAW (SDS),少量整数INT&#xff09;2. List&#xff08;Redis3.2之后使用QuickList实现&#…

electron 使用electron-packager打linux-x64包与linux-arm64包,解决打包缓慢问题

使用electron-packager打linux-x64包与linux-arm64包,解决下载zip打包缓慢问题 在使用electron-packager打包的过程中&#xff0c;需要在第一次下载electron版本对应的zip文件&#xff0c;下载很缓慢&#xff0c;而且还可能出现每次都在下载zip的情况 解决思路是提前下载好zip文…