• 线程八大基础核心七(异常处理)


    1.引子

    在java多线程并发编程中,有八大基础核心。
    看看都有哪八大基础核心呢?它们分别是:
        1.创建线程的方式
        2.线程启动
        3.线程停止
        4.线程生命周期
        5.线程相关的方法
        6.线程相关的属性
        7.线程异常处理
        8.线程安全
    
    今天我们从第七个基础核心开始:线程异常处理

    2.考考你

    #前情回顾
    在软件项目开发中,除了要处理正常的业务流程外,异常处理也是我们绕不过去的一个坎
    
    #考考你
    1.你知道java的异常体系吗?
    2.你知道哪一种异常处理方式比较好吗?
    3.你知道如何使用UncaughtExceptionHandler吗?

    3.案例

    3.1.难以发现的子线程异常

    简述:

    1.在子线程child-exception-0中,抛出异常

    2.主线程main依然正常执行,在实际项目中,会导致难以发现子线程的异常情况

    package com.anan.thread.threadexception;
    
    /**
     * 主线程main不能发现子线程异常
     */
    public class NotFoundChildThreadException {
    
        public static void main(String[] args) {
            // 创建线程对象
            Runnable r1 = new MyRunnable();
            Thread t1 = new Thread(r1,"child-exception-0");
            t1.start();
    
            // 主线程循环打印输出,忽略子线程异常
            for (int i = 0; i < 5; i++) {
                System.out.println("主线程main输出:风景这边独好!当前索引【"
                        + i + "】");
            }
    
        }
    
    }
    
    /**
     * 实现Runnable,创建线程
     */
    class MyRunnable implements Runnable{
        public void run() {
            System.out.println(Thread.currentThread().getName() +
                    "准备抛出异常了...start");
            // 抛出异常
            throw  new RuntimeException("子线程抛出了异常.");
        }
    }

    执行结果:

    3.2.不能捕获的子线程异常

    简述:

    1.创建3个子线程:thread-0、thread-1,thread-2

    2.每个子线程都会抛出异常

    3.在主线程main中,进行捕获处理。期望如果thread-0抛出了异常,那么thread-1/thread-2线程,不要创建执行

    /**
     * 不能捕获的子线程异常
     */
    public class NotCaughtChildException {
    
        public static void main(String[] args) {
            // 预期子线程会抛出异常,通过try{}catch(){}捕获处理
            try{
                // 创建子线程0
                Runnable r1 = new MyRunnable1();
                Thread t0 = new Thread(r1,"thread-0");
                t0.start();
    
                // 创建子线程1
                Thread t1 = new Thread(r1,"thread-1");
                t1.start();
    
                // 创建子线程2
                Thread t2 = new Thread(r1,"thread-2");
                t2.start();
    
            }catch (RuntimeException e){
                System.out.println("捕获到了异常.");
            }
        }
    }
    
    /**
     * 实现Runnable,创建线程
     */
    class MyRunnable1 implements Runnable{
        public void run() {
            System.out.println(Thread.currentThread().getName() +
                    "准备抛出异常了...start");
            // 抛出异常
            throw  new RuntimeException("子线程抛出了异常.");
        }
    }

    执行结果:

    3.3.全局异常处理

    简述:

    1.在3.2.中,不能通过try{}catch(){}捕获子线程异常。因为try{}catch(){}只能捕获当前线程的异常

    2.如果要对所有子线程,进行统一异常处理,需要一个全局异常处理器

    3.全局异常处理器接口:Thread.UncaughtExceptionHandler

    4.实现方式:

    4.1.编写全局异常处理器,实现接口:Thread.UncaughtExceptionHandler
    4.2.注册使用全局异常处理器

    3.3.1.全局异常处理器

    package com.anan.thread.threadexception;
    
    /**
     * 自定义全局异常处理器类
     */
    public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println(t.getName() + "发生了异常,异常消息:" + e.getMessage());
        }
    }

    3.3.2.注册使用全局异常处理器

    package com.anan.thread.threadexception;
    
    /**
     * 注册使用自定义全局异常处理器
     */
    public class UseUncaughtExceptionHandler {
    
        public static void main(String[] args) {
    
            // 关键代码:设置全局异常处理器
            Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
    
            // 创建子线程0
            Runnable r1 = new MyRunnable1();
            Thread t0 = new Thread(r1,"thread-0");
            t0.start();
    
            // 创建子线程1
            Thread t1 = new Thread(r1,"thread-1");
            t1.start();
    
            // 创建子线程2
            Thread t2 = new Thread(r1,"thread-2");
            t2.start();
        }
    }
    
    /**
     * 实现Runnable,创建线程
     */
    class MyRunnable2 implements Runnable{
        public void run() {
            System.out.println(Thread.currentThread().getName() +
                    "准备抛出异常了...start");
            // 抛出异常
            throw  new RuntimeException("子线程抛出了异常.");
        }
    }

    3.3.3.执行结果

    4.讨论分享

    #考考你答案
    1.你知道java的异常体系吗?
      1.1.java异常体系中,老祖宗是Throwable
      1.2.在Throwable下,有Exception异常体系(日常开发中,见得最多)
      1.3.在Throwable下,有Error错误体系(日常开发中,较少关注)
        
    2.你知道哪一种异常处理方式比较好吗?
      2.1.通过案例演示,我们知道不能通过try{}catch(){},跨线程捕获异常。try{}catch(){}只能捕获当前线程自己的异常
      
      2.2.处理方式一:
       2.2.1.可以在当前线程中进行try{}catch(){},捕获处理当前线程的异常
       2.2.2.该种方式处理起来代码量多、繁琐。不推荐使用
       
      2.3.处理方式二:
       2.3.1.通过设置全局异常处理器:UncaughtExceptionHandler
       2.3.2.实现异常全局统一处理。推荐使用
       
    3.你知道如何使用UncaughtExceptionHandler吗?
      3.1.编写全局异常处理器,实现接口:
       Thread.UncaughtExceptionHandler
      3.2.注册使用全局异常处理器:
       // 关键代码:设置全局异常处理器
            Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

    java异常体系类图

  • 相关阅读:
    (译).NET4.X并行任务Task需要释放吗?
    微软面向高并发应用而推出的新程序库——TPL Dataflow
    C# 5.0 Async函数的提示和技巧
    内存泄露——文章
    AJAX POST请求中参数以form data和request payload形式在php中的获取方式
    NodeJS中间层搭建
    HTML5上传预览
    laravel 图片上传 ajax 方式
    抽奖程序
    IText 生成页脚页码
  • 原文地址:https://www.cnblogs.com/itall/p/12315722.html
Copyright © 2020-2023  润新知