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

看下面的例子:

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class ExceptionThread implements Runnable {

@Override

public void run() {

throw new RuntimeException("这个线程就干了这么一件事,抛出一个运行时异常");

}

public static void main(String[] args) {

try {

ExecutorService exec = Executors.newCachedThreadPool();

exec.execute(new ExceptionThread());

System.out.println("该干嘛干嘛去");

} catch (RuntimeException e) {

System.out.println("能不能捕获到异常?");

}

}

}

运行结果:

该干嘛干嘛去

Exception in thread "pool-1-thread-1" java.lang.RuntimeException: 这个线程就干了这么一件事,抛出一个运行时异常

at ExceptionThread.run(ExceptionThread.java:8)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

at java.lang.Thread.run(Thread.java:619)

从运行结果中,我们可以看到的是,这个异常在main线程中没有catch到,即

System.out.println("能不能捕获到异常?");

永远不会执行到。

问题来了,我们如果需要捕获其线程的unchecked异常时该怎么办?Java SE5之后,我们可以通过Executor来解决这个我问题。为了解决这个问题,我们需要修改Executor产生线程的方式。Thread.UncaughtExceptionHandler是java SE5中的新接口,它允许我们在每一个Thread对象上添加一个异常处理器。(UncaughtExceptionHandler)。Thread.UncaughtExceptionHandler.uncaughtException()方法会在线程因未捕获的异常而面临死亡时被调用。下面这个例子简单的演示了如何使用UncaughtExceptionHandler

import java.lang.Thread.UncaughtExceptionHandler;

/**

* 用于捕获异常---捕获的是uncheckedException

*

* @author February30th

*

*/

public class MyUnchecckedExceptionhandler implements UncaughtExceptionHandler {

@Override

public void uncaughtException(Thread t, Throwable e) {

System.out.println("捕获到异常:" + e);

}

}

import java.util.concurrent.ThreadFactory;

public class HandlerThreadFactory implements ThreadFactory {

@Override

public Thread newThread(Runnable r) {

System.out.println("创建一个新的线程");

Thread t = new Thread(r);

t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());

System.out.println("eh121 = " + t.getUncaughtExceptionHandler());

return t;

}

}

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class ThreadExceptionTest {

/**

* @param args

*/

public static void main(String[] args) {

//下面有3中方式来执行线程。

//第1种按照普通的方式。这是能捕获到异常

Thread t = new Thread(new ExceptionThread2());

t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());

t.start();

//第2种按照现成池,直接按照thread方式,此时不能捕获到异常,为什么呢?因为在下面代码中创建了一个线程,且设置了异常处理器,

//但是呢,在我们线程池中会重设置新的Thread对象,而这个Thread对象没有设置任何异常处理器,换句话说,我们在线程池外对线程做的

//任何操作都是没有用的

ExecutorService exec1 = Executors.newCachedThreadPool();

Runnable runnable = new ExceptionThread2();

Thread t1 = new Thread(runnable);

t1.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());

exec1.execute(runnable);

//第3种情况一样的,也是走的线程池,但是呢是通过ThreadFactory方式,在ThreadFactory中会对线程做一些控制,可以设置异常处理器

//此时是可以捕获异常的。

ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());

exec.execute(new ExceptionThread2());

}

}

运行结果

创建一个新的线程

eh121 = MyUnchecckedExceptionhandler@1b8e059

run() byThread[Thread-0,5,main]

eh=MyUnchecckedExceptionhandler@1b8e059

捕获到异常:java.lang.RuntimeException: 抛出运行时异常

从上述的运行结果中可以看到,未捕获的异常是通过uncaughtException来捕获的。

按照上述的实例,我们可以按照具体的情况,逐个地设置处理器。但是如果我们知道将要在代码的所有地方都是用相同的异常处理器,那么更简单的方式是在Thread类中设置一个静态域,并将这个处理器设置为默认的未捕获异常处理器。看下面的例子:

Thread.setDefaultUncaughtExceptionHandler(newMyUnchecckedExceptionhandler());

ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());

exec.execute(new ExceptionThread2());

这个默认的处理器只有在线程不存在非默认的异常处理器时才会调用。 在运行时,系统会检查线程是否有属于自己的异常处理器,如果发现没有,就去检查相应的线程组是否有专有的异常处理器,如果发现也没有,再调用默认的异常处理器。

摘自:http://www.cnblogs.com/chenfei0801/archive/2013/04/23/3039286.html

java runnable 异常_JAVA 线程中的异常捕获相关推荐

  1. JAVA语言异常_Java语言中常用异常类EoFException是用来处理( )异常的类_学小易找答案...

    [填空题]Java语言中常用异常类ClassNotFoundException是用来处理 ( )的异常的类 [填空题]Java语言声明 ( ) 类为会产生"严重错误"的类 [简答题 ...

  2. 线程java买火车票_Java线程中卖火车票问题的深入讲解

    用java代码模拟卖100张火车票问题:四个售票窗口同时售票且不能卖出同一张火车票. 代码如下. package lesson; public class demo1 { public static ...

  3. java异常处理机制_Java编程中的异常机制

    本文旨在以初学者的角度来学习Java异常的知识,尽量简单,一些细枝末节的知识不会讲述,但不影响对知识的掌握. (比如try-catch可以嵌套,不太会这么用) 1.什么是异常 我们先举个例子 int ...

  4. java 同步锁_java线程中的同步锁和互斥锁有什么区别?

    在java中,同步锁和互斥锁英文关键字都是Synchronized,没有本质上的区别,两者都包括对资源的独占,使用起来没有区别.概念上的区别是 1:互斥是通过竞争对资源的独占使用,彼此没有什么关系,执 ...

  5. java run 方法_java线程中的run()方法能有几个啊?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 给个例子 package test; public class Test{ public static void main(String[] args){ ...

  6. java主线程捕获子线程中的异常

    java主线程捕获子线程中的异常 参考文章: (1)java主线程捕获子线程中的异常 (2)https://www.cnblogs.com/jpfss/p/10272726.html (3)https ...

  7. 为什么要处理子线程中的异常?不处理可以吗?那该如何处理?

    声明:尊重他人劳动成果,转载请附带原文链接!学习交流,仅供参考! 文章目录 1.前言:我们知道在单线程程序可以轻松发现异常,那么为什么子线程为什么不能轻松发现异常? 2.常见错误一 原因分析 3.常见 ...

  8. 青铜9:防患未然-如何处理线程中的异常

    欢迎来到<并发王者课>,本文是该系列文章中的第9篇. 在本篇文章中,我将为你介绍线程中异常的处理方式以及uncaughtExceptionHandler用法. 一.新线程中的异常去哪了 应 ...

  9. C#多线程开发-处理子线程中的异常

    C#多线程开发-处理子线程中的异常 在平时的多线程开发中,对于异常的处理是至关重要的,千万不能马虎.如果在实际的项目中,对于某些线程中的异常没有处理,会直接导致整个程序崩溃,软件无法使用. 其中需要说 ...

最新文章

  1. 后台开发经典书籍--unix网络编程
  2. notes邮件正文显示不全_Outlook邮件中的可操作消息(Actionable Message)
  3. 聊聊JVM(八)说说GC标记阶段的一些事
  4. Codeforces Round #691 (Div. 2)
  5. 跟着太白老师学python day11 可迭代对象和迭代器
  6. 程序员!别逼自己买课了,每天花10分钟做这件事,写代码能力暴增......
  7. table标签+css代码实现选项卡效果(用)
  8. java提示框easyui风格_[Java教程]jQuery EasyUI 提示框(Messager)用法
  9. kibana报错Request Timeout after 30000ms故障解决
  10. SSM框架中出现的几种注解的理解
  11. redis缓存和mysql数据库同步
  12. 窄带包络解调python实现_对数据包络分析法DEA的再理解,以及python 实现
  13. java 文档比较功能_java 实现在线比较两个版本的Word文档的功能
  14. 如何提高射频信号发生器的性能
  15. 成考本科计算机找工作有用吗,成人本科学历找工作有用吗 就业困难吗
  16. 杜比介绍 杜比数位 Dolby
  17. ubuntu18.04修改mac地址
  18. 华为mate40计算机,华为Mate40 Pro+电脑,工作事半功倍就差这一步
  19. 云栖科技评论84期:英国零售商找错了“替罪羊”...
  20. 关于Tag和Tags

热门文章

  1. 为什么MySQL索引要使用 B+树,而不是其它树形结构?
  2. 程序员是青春饭吗 - CSDN分享会笔记
  3. 【Flask】jinja2根据url中的字符串,决定是否显示某个div
  4. 数据库存储模型-数据存储
  5. spring与cxf的整合
  6. RSS、RSSI以及dBm相关概念
  7. 【详细注释】1051 Pop Sequence (25 分)
  8. 13行代码AC_Justifying the Conjecture Gym - 102394J(解题报告)
  9. Spring容器创建过程
  10. Here Document和Expect概述(免交互,变量设定,控制,注释,)(shell里使用EOF报错)