Java多线程异常处理

文章介绍了Java中线程出现异常时的默认处理方式,以及如何通过setUncaughtExceptionHandler()和setDefaultUncaughtExceptionHandler()方法集中处理线程异常,避免代码冗余。同时,文章提到了线程组在现代Java编程中的过时地位,虽然线程组可以管理异常,但在Java9中已标记为过时,推荐使用线程池等高级并发工具。
摘要由CSDN通过智能技术生成

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值