线程八大基础核心七(异常处理)
小杨【0和1】 人气:01.引子
在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异常体系类图:
加载全部内容