在Java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉。这一点是通过java.lang.Runnable.run()方法声明(因为此方法声明上没有throw exception部分)进行了约束。但是线程依然有可能抛出unchecked exception,当此类异常抛出时,线程就会终结,而对于主线程和其他线程完全不受影响,且完全感知不到某个线程抛出的异常(也是说完全无法catch到这个异常)。JVM的这种设计源自于这样一种理念:“线程是独立执行的代码片断,线程的问题应该由线程自己来解决,而不要委托到外部。”基于这样的设计理念,在Java中,线程方法的异常(无论是checked还是unchecked exception),都应该在线程代码边界之内(run方法内)进行try catch并处理掉。下面看两个例子:

例子一:IOException是一个chedked exception,在这里看到了报错,编译不通过。

例子二:想捕线程的非检查异常,发现也不能捕获

public class MyThread2 implements Runnable {
@Override
public void run() {
int i = 1/0; //此处会报非检查异常
} public static void main(String[] args) {
try {
Thread t = new Thread(new MyThread2());
t.start();
} catch (Exception e) {
//想在外面捕获异常,但是获取不到
System.out.println("分母不能是零啊");
}
}
}

运行结果:

Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
at org.burning.sport.javase.thread.MyThread2.run(MyThread2.java:11)
at java.lang.Thread.run(Thread.java:745)

从运行结果看到,catch代码块中并没有打印输出

那如果我们需要捕获线程跑出的异常并做处理的话改怎么办呢?

  方法一:在run()方法中用try catch来捕获这个异常并做处理

public class MyThread implements Runnable {
@Override
public void run() {
try {
int i = 1/0;
} catch (Exception e) {
System.out.println("这里有问题,可以通知给其他人:" + e); //这里可以做捕获异常后的其他操作,比如发消息给第三方
}
} public static void main(String[] args) {
Thread t = new Thread(new MyThread());
t.start();
}
}

结果:

这里有问题,可以通知给其他人:java.lang.ArithmeticException: / by zero

  方法二:我们想在线程边界之外捕获这个异常的(run()方法之外)的话,那我们就要用到Java给我们提供的UncaughtExceptionHandler处理方法

步骤一:定义一个自己的异常处理器

package org.burning.sport.javase.thread.exception;

public class MyUncatchException implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("当前线程的名字:" + t.getName());
System.out.println("发生了什么问题:" + e );
}
}

步骤二:在线程启动前设置自定义的异常处理器

package org.burning.sport.javase.thread.exception;

public class ExceptionThread implements Runnable {
@Override
public void run() {
System.out.println("将要悲剧了");
int i = 1/0; } public static void main(String[] args) {
Thread t = new Thread(new ExceptionThread());
//这里设置自定义的异常处理器
t.setUncaughtExceptionHandler(new MyUncatchException());
t.start();
}
}

结果:

将要悲剧了
当前线程的名字:Thread-0
发生了什么问题:java.lang.ArithmeticException: / by zero

小结:

  如果在run方法中没有发生异常,那么就不会去运行MyUncatchException

如果用线程池来启动线程的话还可以用ThreadFactory来设置异常处理器

步骤一:同上

步骤二:自定义一个ThreadFactory

package org.burning.sport.javase.thread.exception;

import java.util.concurrent.ThreadFactory;

public class HandlerThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
System.out.println("线程名称:" + t);
t.setUncaughtExceptionHandler(new MyUncatchException()); //设置异常处理器
System.out.println("好恐怖:" + t.getUncaughtExceptionHandler());
return t;
}
}

步骤三:通过线程池启动线程

package org.burning.sport.javase.thread.exception;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ExceptionThread implements Runnable {
@Override
public void run() {
System.out.println("将要悲剧了");
int i = 1/0;
} public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
exec.execute(new ExceptionThread());
}
}

结果:

线程名称:Thread[Thread-0,5,main]
好恐怖:org.burning.sport.javase.thread.exception.MyUncatchException@4b9af9a9
将要悲剧了
线程名称:Thread[Thread-1,5,main]
好恐怖:org.burning.sport.javase.thread.exception.MyUncatchException@34d6cbd5
当前线程的名字:Thread-0
发生了什么问题:java.lang.ArithmeticException: / by zero

参考:

[1] 博客,https://www.cnblogs.com/brolanda/p/4725138.html

最新文章

  1. .NET基础拾遗(4)委托、事件、反射与特性
  2. W3School-CSS 背景实例
  3. npm淘宝镜像
  4. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
  5. Java类成员(成员变量和方法)的覆盖与隐藏归纳
  6. SpringMVC学习系列(12) 完结篇 之 基于Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现
  7. go get 获得 golang.org 的项目
  8. seq命令
  9. 关于javascript 回调函数
  10. python网络编程之socket
  11. 1.js编程风格。 --- 编写可维护的javascript
  12. Zepto swipe 无效(坑)
  13. Fragment 学习笔记(1)
  14. 初识webview
  15. [国嵌笔记][006][Linux文本编辑器]
  16. Go 语言结构体
  17. spark2.4 分布式安装
  18. 连阿里都在用它处理亿万级数据统计,论其对Java程序员的重要性!
  19. JAVA基础搬运工
  20. CC2541设置中断输入模式

热门文章

  1. 【转】彻底理解js中this的指向,不必硬背。
  2. [代码审计]青云客Cms前台有条件注入至getshell,后台xss至getshell、至弹你一脸计算器
  3. 给 Android 开发者的一点福利:免费模拟面试
  4. npm ERR! code EINTEGRITY npm! ERR! shal-
  5. 关于OC中浮点型的计算
  6. 5、ABPZero系列教程之拼多多卖家工具 修改User表结构
  7. ConcurrentHashMap源码阅读
  8. Zabbix实战-简易教程(1)--总流程
  9. jQuery实现跨域请求实例
  10. hihocoder-1079题解(线段树+离散化)