在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 {@Overridepublic 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.RuntimeExceptionat 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 {@Overridepublic void uncaughtException(Thread t, Throwable e) {System.out.println("caught " + e);}
}class HandlerThreadFactory implements ThreadFactory {@Overridepublic 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

转载于:https://www.cnblogs.com/onlysun/p/4601430.html

Java多线程异常处理相关推荐

  1. 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)

    在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...

  2. java多线程 异常处理_Java8多线程ForkJoinPool:处理异常

    java多线程 异常处理 引入Java8 lambda背后的主要动机之一是能够尽可能轻松地使用多核的能力(请参阅精通Lambdas:多核世界中的Java编程 ). 只需将代码从collection.s ...

  3. Java 异常处理(标准抛异常、异常处理、多异常、Finally、多线程异常处理、获取异常的堆栈信息、链试异常、自定义异常)

    使用 catch 处理异常(标准抛异常) public class Main {public static void main (String args[]) {int array[]={20,20, ...

  4. java多线程中的异常处理

    2019独角兽企业重金招聘Python工程师标准>>> 在java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的che ...

  5. Java 多线程编程之 interruptException

    下面是java 多线程中的异常处理: package multithread; public class InterruptException { public static void main(St ...

  6. Java多线程:线程间通信之Lock

    Java 5 之后,Java在内置关键字sychronized的基础上又增加了一个新的处理锁的方式,Lock类. 由于在Java线程间通信:volatile与sychronized中,我们已经详细的了 ...

  7. 【多线程编程学习】java多线程基于数据分割的大文件下载器

    文章目录 代码:基于数据分割的大文件下载器 作为包装的存储对象类: 主文件下载类: 子任务下载类: 处理缓存: 启动类: 数据分割思想产生的问题 代码来自书籍<java多线程编程实战指南> ...

  8. Java多线程并发编程

    一.线程池 1.1.什么是线程池 线程池是一种多线程的处理方式,利用已有线程对象继续服务新的任务(按照一定的执行策略),而不是频繁地创建销毁线程对象,由此提高服务的吞吐能力,减少CPU的闲置时间.具体 ...

  9. java多线程基础概念

    大纲:java多线程知识体系` 程序`:为了完成某一功能, (用某种语言编写的一组指令的集合),是一段静态的代码块 进程:程序的一次执行过程,是正在运行的程序,有着完整的生命周期,是资源分配的基本单位 ...

最新文章

  1. WatchStor观察:思科携EMC等合作伙伴 圈地数据中心市场
  2. OVS 各功能调用过程(三十一)
  3. C中结构体的存储分配
  4. centos+nginx+php+mysql(经典架构流程案例)
  5. sklearn 主成分分析法 PCA和IPCA
  6. Adobe Reader 9.0记住阅读位置
  7. 有限元分析简介及伽辽金法
  8. 中国古代诗词文本挖掘项目
  9. WordPress 跨站请求伪造漏洞
  10. 读书 -- 偷偷暗时间之《暗时间》总结
  11. 部署blog的时候,出现了以下错误
  12. Espresso Idling Resource
  13. 路径中的“./“,“../“,“/“ 代表的含义
  14. 解除封闭、寒假延长!多校发通知!
  15. php 课程设计总结心得体会,课程设计心得体会
  16. pcolor和surf画出的图形转存为eps或pdf格式出现横竖斜白色虚线网格,完美去掉!!!
  17. 不错的讲解业务架构,应用架构,数据架构的图
  18. UIUC计算机科学系博士,PhD捷报|计算机博士全美TOP5!清华首批UIUC CS PhD全奖!恭喜Nuts清华学员!...
  19. 服务器风扇插头型号,服务器风扇专场 台达 12V   12CM 4.8A怪兽来袭只要15元
  20. “做产品的”,如何自我调节:一封家书,给同学们参考

热门文章

  1. 输出一个文件的最后n行数据,如果文件总行数不足n行,则显示全部数据
  2. 微软面试题:有100万个数字(1到9),其中只有1个数字重复2次,如何快速找出该数字
  3. React开发(252):react项目理解 ant design spining加载中
  4. [html] HTML5如何监听video的全屏和退出全屏?
  5. [html] H5如何与APP交互?有哪些方式?
  6. [vue] vue生命周期的作用是什么?
  7. [css] 举例说明css的基本语句构成是什么呢?
  8. [css] 使用纯css来创建一个滑块
  9. 前端学习(2690):重读vue电商网站11之使用树形控件 el-tree
  10. “约见”面试官系列之常见面试题之第八十六篇之nexttick(建议收藏)