Java~什么是线程组? 演示线程与线程组的统一异常处理器Handler

线程组

  • 可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程。这样的组织结构有些类似于树的形式。
    在这里插入图片描述
  • 线程组的作用是,可以批量的管理线程或线程组对象,有效地对线程或线程组对象进行组织。

线程对象关联线程组 (一级管关联)

  • 所谓的1级关联就是父对象中有子对象,但并不创建子孙对象。这种情况经常出现在开发中,比如创建一些线程时,为了有效地对这些线程进行组织管理,通常的情况下是创建一个线程组,然后再将部分线程归属到该组中。这样的处理可以对零散的线程对象进行有效的组织与规划。
  • 演示
public class Demo1 {

    public static void main(String[] args) {
        //创建俩个runnable
        Runnable runnableA = new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread().getName() + " " +
                            Thread.currentThread().getThreadGroup().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        };
        Runnable runnableB = new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread().getName() + " " +
                            Thread.currentThread().getThreadGroup().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        };
        //创建一个ThreadGroup
        ThreadGroup threadGroup = new ThreadGroup("Listen的Group");
        //创建俩个线程去执行runnable
        Thread a = new Thread(threadGroup, runnableA, "A");
        Thread b = new Thread(threadGroup, runnableB, "B");
        System.out.println(Thread.currentThread().getName() + " " +
                Thread.currentThread().getThreadGroup().getName());
        a.start();
        b.start();
    }
}

在这里插入图片描述

  • 所谓的多级关联就是父对象中有子对象,子对象中再创建子对象,也就是出现子孙对象的效果了。但是此种写法在开发中不太常见,如果线程树结构设计得非常复杂反而不利于线程对象的管理
  • 线程组有自动归属的特性, 就是如果你在主线程main中创建一个线程组, 即使你不把他归属到main这个线程组中, 他也会自动归属.

线程组的批量停止

  • 通过将线程归属到线程组中,当调用线程组ThreadGroup的interrupt(方法时,可以将该组中的所有正在运行的线程批量停止。
public class Demo2 {

    public static void main(String[] args) throws InterruptedException {
        //创建俩个runnable
        Runnable runnableA = new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread().getName() + " " +
                            Thread.currentThread().getThreadGroup().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        //如果线程再sleep中被打断, 那么在捕获异常的时候会清除打断的这个标记
                        //所以要在这里break掉
                        break;
                    }
                }

            }
        };
        Runnable runnableB = new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread().getName() + " " +
                            Thread.currentThread().getThreadGroup().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }

            }
        };
        //创建一个ThreadGroup
        ThreadGroup threadGroup = new ThreadGroup("Listen的Group");
        //创建俩个线程去执行runnable
        Thread a = new Thread(threadGroup, runnableA, "A");
        Thread b = new Thread(threadGroup, runnableB, "B");
        System.out.println(Thread.currentThread().getName() + " " +
                Thread.currentThread().getThreadGroup().getName());
        a.start();
        b.start();
        Thread.sleep(3000);
        System.out.println(threadGroup.getName() + " 线程打断");
        threadGroup.interrupt();
    }
}

在这里插入图片描述

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

指定线程对象进行异常统一处理

  • 下面代码程序运行后在控制台输出空指针异常。在Java的多线程技术中,可以对多线程中的异常进
    行“捕捉”,使用的是UncaughtExceptionHandler类,从而可以对发生的异常进行有效的处理。
  • 演示
public class Demo3 {

    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        threadA.setName("A");
        //如果这样直接start执行 肯定会抛出一个异常 但是执行了setUncaughtExceptionHandler方法
        //重写了uncaughtException就会自动捕捉异常
        threadA.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println(ThreadA.currentThread().getName() + " 抛出了异常");
            }
        });
        threadA.start();
    }
}

class ThreadA extends Thread {

    @Override
    public void run() {
        //抛出一个异常
        String s = null;
        s.getBytes();
    }

}

在这里插入图片描述

  • 方法setUncaughtExceptionHandler()的作用是对指定的线程对象设置默认的异常处理器。

指定线程类的所有线程对象进行异常统一处理

  • 方法setUncaughtExceptionHandler()是给指定线程对象设置的异常处理器。在Thread类中还可以使用setDefaultUncaughtExceptionHandler()方法对所有线程对象设置异常处理器。
  • 演示
public class Demo4 {

    public static void main(String[] args) {
        //给ThreadB执行一个统一异常处理器
        ThreadB.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println(t.getName() + " 出现异常我捕获了");
            }
        });

        ThreadB threadB = new ThreadB();
        threadB.setName("B");
        ThreadB threadB1 = new ThreadB();
        threadB1.setName("BB");
        threadB.start();
        threadB1.start();
    }
}

class ThreadB extends Thread {

    @Override
    public void run() {
        //抛出一个异常
        String s = null;
        s.getBytes();
    }

}

在这里插入图片描述

  • 方法setDefaultUncaughtExceptionHandler()的作用是为指定线程类的所有线程对象设置默认的异常外理器。

线程组内异常处理器

  • 演示
public class Demo5 {

    public static void main(String[] args) {

        ThreadGroup group = new ThreadGroup("Listen的group") {
            //给这个线程组进行统一异常处理
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                //t表示出现异常的是哪个线程 e表示异常
                super.uncaughtException(t, e);
                System.out.println(t.getName() + " 出现异常我捕获了");
            }
        };

        //创建5个正常线程放到我的线程组中
        MyThread[] myThreads = new MyThread[5];
        for (int i = 0; i < 5; i++) {
            myThreads[i] = new MyThread(group, "线程" + i, "" + i);
            myThreads[i].start();
        }
        //
        MyThread myThread = new MyThread(group, "出错线程001", "ab");
        myThread.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() {
        //num为字符串的时候 这里会抛出异常
        int num = Integer.parseInt(this.num);
        while (true) {
            System.out.println(Thread.currentThread().getName() + " 死循环中");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}

在这里插入图片描述

  • 从运行的结果来看,在默认的情况下和给了统一异常处理下,线程组中的一个线程出现异常不会影响其他线程的运行。
  • 需要注意的是 使用自定义java.lang.ThreadGroup线程组,并且重写uncaughtException方法处理组内线程中断行为时,每个线程对象中的run()方法内部不要有异常catch语句,如果有catch语句, 则public void uncaughtException (Thread t, Throwablee)方法不执行。

线程异常处理的传递

  • 首先在run方法看有没有catch语句, 如果没有, 就在看这个线程对象有没有异常处理器, 再看这个线程类有没有统一异常处理, 最后再看这个线程组有没有统一异常处理器.
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值