Java多线程异常处理
在java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉。这一点是通过java.lang.Runnable.run()方法声明(因为此方法声明上没有throws exception部分)进行了约束。但是线程依然有可能抛出unchecked exception,当此类异常跑抛出时,线程就会终结,而对于主线程和其他线程完全不受影响,且完全感知不到某个线程抛出的异常(也是说完全无法catch到这个异常)。JVM的这种设计源自于这样一种理念:“线程是独立执行的代码片断,线程的问题应该由线程自己来解决,而不要委托到外部。”基于这样的设计理念,在Java中,线程方法的异常(无论是checked还是unchecked exception),都应该在线程代码边界之内(run方法内)进行try catch并处理掉.
public class ExeceptionThread implements Runnable {
@Override
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) {
try {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExeceptionThread());
} catch (Exception e) { //捕获不了
System.out.println("exeception has handled");
}
}
}
Exception in thread "pool-1-thread-1" java.lang.RuntimeException
at Thread.Exection.ExeceptionThread.run(ExeceptionThread.java:10)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
但如果线程确实没有自己try catch某个unchecked exception,而我们又想在线程代码边界之外(run方法之外)来捕获和处理这个异常的话,java为我们提供了一种线程内发生异常时能够在线程代码边界之外处理异常的回调机制,即Thread对象提供的setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)方法。
通过该方法给某个thread设置一个UncaughtExceptionHandler,可以确保在该线程出现异常时能通过回调UncaughtExceptionHandler接口的public void uncaughtException(Thread t, Throwable e) 方法来处理异常,这样的好处或者说目的是可以在线程代码边界之外(Thread的run()方法之外),有一个地方能处理未捕获异常。但是要特别明确的是:虽然是在回调方法中处理异常,但这个回调方法在执行时依然还在抛出异常的这个线程中!另外还要特别说明一点:如果线程是通过线程池创建,线程异常发生时UncaughtExceptionHandler接口不一定会立即回调。
class ExceptionThread2 implements Runnable {
public void run() {
Thread t = Thread.currentThread();
System.out.println("run() by " + t);
System.out.println("eh=" + t.getUncaughtExceptionHandler());
throw new RuntimeException();
}
}
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("caught " + e);
}
}
class HandlerThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
System.out.println(this + " creating new Thread");
Thread t = new Thread(r);
System.out.println("created " + t + " ID:" + t.getId());
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
System.out.println("eh=" + t.getUncaughtExceptionHandler());
return t;
}
}
public class CaptureUncaughtException {
public static void main(String[] args) {
ExecutorService exec = Executors
.newCachedThreadPool(new HandlerThreadFactory());
exec.execute(new ExceptionThread2());
}
}
Thread.Exection.HandlerThreadFactory@4e25154f creating new Thread
created Thread[Thread-0,5,main] ID:9
eh=Thread.Exection.MyUncaughtExceptionHandler@70dea4e
run() by Thread[Thread-0,5,main]
eh=Thread.Exection.MyUncaughtExceptionHandler@70dea4e
Thread.Exection.HandlerThreadFactory@4e25154f creating new Thread
created Thread[Thread-1,5,main] ID:11
eh=Thread.Exection.MyUncaughtExceptionHandler@193fa958
caught java.lang.RuntimeException
默认方式:
public class SettingDefaultHandler {
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(
new MyUncaughtExceptionHandler());//线程默认异常捕获器类
ExecutorService exec=Executors.newCachedThreadPool();
exec.execute(new ExceptionThread2());
}
}
run() by Thread[pool-1-thread-1,5,main]
eh=java.lang.ThreadGroup[name=main,maxpri=10]
caught java.lang.RuntimeException
比之上述方法,还有一种编程上的处理方式可以借鉴,即,有时候主线程的调用方可能只是想知道子线程执行过程中发生过哪些异常,而不一定会处理或是立即处理,那么发起子线程的方法可以把子线程抛出的异常实例收集起来作为一个Exception的List返回给调用方,由调用方来根据异常情况决定如何应对。不过要特别注意的是,此时子线程早以终结。
Java thread里面关于异常的部分比较奇特。一般在线程里碰到checked exception,推荐的做法是采用try/catch块来处理。而对于unchecked exception,比较合理的方式是注册一个实现UncaughtExceptionHandler接口的对象实例来处理。
参考:http://www.cnblogs.com/zhuawang/p/3751875.html
http://blog.csdn.net/bluishglc/article/details/8216824
Java多线程异常处理的更多相关文章
- 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)
在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...
- 从零开始学习Java多线程(二)
前面已经简单介绍进程和线程,为后续学习做铺垫.本文讨论多线程传参,Java多线程异常处理机制. 1. 多线程的参数传递 在传统开发过程中,我们习惯在调用函数时,将所需的参数传入其中,通过函数内部逻辑处 ...
- Java多线程中的异常处理
在java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉.这一点是通过java.lang.Run ...
- Java多线程编程核心技术---拾遗增补
线程状态验证 public class MyThread extends Thread { public MyThread() { System.out.println("构造方法中的状态: ...
- Java多线程:线程间通信之Lock
Java 5 之后,Java在内置关键字sychronized的基础上又增加了一个新的处理锁的方式,Lock类. 由于在Java线程间通信:volatile与sychronized中,我们已经详细的了 ...
- 从零开始学习Java多线程(三)
本文主要对Java多线程同步与通信以及相关锁的介绍. 1 .Java多线程安全问题 Java多线程安全问题是实现并发最大的问题,可以说多线程开发其实就是围绕多线程安全问题开发,涉及之深,不是简简单单一 ...
- Java多线程面试题整理
部分一:多线程部分: 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速. ...
- Java多线程核心技术(六)线程组与线程异常
本文应注重掌握如下知识点: 线程组的使用 如何切换线程状态 SimpleDataFormat 类与多线程的解决办法 如何处理线程的异常 1.线程的状态 线程对象在不同运行时期有不同的状态,状态信息就处 ...
- Java多线程编程实战指南(核心篇)读书笔记(四)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76690961冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
随机推荐
- shell的含义
shell:壳,是操作linux最直接的方式,通过shell中输入命令和linux系统进行交互. shell是一个小盒子,每一个有独立的命名空间,登录后的操作就是一个shell(有可能是bash,zs ...
- Head First设计模式之目录
只有沉淀.积累,才能远航:沉沉浮浮,脚踏实地. 这本书已经闲置了好久,心血来潮,决定写个目录,让自己坚持看完这本书 创建型模式 抽象工厂模式(Abstract factory pattern): 提供 ...
- 利用Service Fabric承载eShop On Containers
从模块化到微服务化 从Pet Shop 到eShop on Container都是Microsoft在技术演进的路径上给开发者展示.Net的开发能力和架构能力的Sample工程,Petshop的时候更 ...
- 2017春 前端自动化(二) 页面自动刷新、sass与css转换的使用、pxToRem直观转换
2017春 前端自动化(二) 页面自动刷新.sass与css转换的使用.pxToRem直观转换 引言: 此文要演示:浏览器页面自动刷新:移动端px与rem的转换,简单直观化:使用sass自动生 ...
- Python 数据科学系列 の Numpy、Series 和 DataFrame介绍
本課主題 Numpy 的介绍和操作实战 Series 的介绍和操作实战 DataFrame 的介绍和操作实战 Numpy 的介绍和操作实战 numpy 是 Python 在数据计算领域里很常用的模块 ...
- windows 下进程池的操作
在Windows上创建进程是一件很容易的事,但是在管理上就不那么方便了,主要体现在下面几个方面: 1. 各个进程的地址空间是独立的,想要在进程间共享资源比较麻烦 2. 进程间可能相互依赖,在进程间需要 ...
- 使用JavaScript 操作本地文件
一.显示用户选择文件[图片] <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
- Django-- 多数据库联用
django项目中使用多个数据库的方法, 多个数据库的联用 以及多数据库时数据导入导出的方法. 直接给出一种简单的方法吧,想了解更多的到官方教程,点击此处 给每个app都可以单独的设置一个数据库 se ...
- es6 模板字变量和字符串占位符
开发者一直在寻找一种创建多行字符串的形式,但要使用单引号双引号字符串一定要在同一行才行. 老办法: 还有其他办法,虽然能实现,但是太啰嗦 es6模板自变量 使用反撇好(`)替换了单双引号 反撇好中的所 ...
- Springboot(一):使用Intellij中的Spring Initializr来快速构建Spring Boot工程
使用Intellij中的Spring Initializr来快速构建Spring Boot工程 New---Project 可以看到图所示的创建功能窗口.其中Initial Service Url指向 ...