[转]Java中主线程如何捕获子线程抛出的异常_java 主线程捕获子线程异常-程序员宅基地

技术标签: exception  java  application  string  returning  thread  

这么来看待这个问题。首先明确线程代码的边界。其实很简单,Runnable接口的run方法所界定的边界就可以看作是线程代码的边界。Runnable接口中run方法原型如下:  
  <<  
          public   void   run();  
  >>  
 
而所有的具体线程都实现这个方法,所以这里就明确了一点,线程代码不能抛出任何checked异常。所有的线程中的checked异常都只能被线程本身消化掉。:)   这样本身也是符合线程的设计理念的,线程本身就是被看作独立的执行片断,它应该对自己负责,所以由它来消化所有的checked异常是很正常的。  
 
这样就回答了楼主的第一个问题:checked异常一定要在线程内部消化。  
   
 
但是,线程代码中是可以抛出错误(Error)和运行级别异常(RuntimeException)的。Error俺们可以忽略,因为通常Error是应该留给vm的,而RuntimeException确是比较正常的,如果在运行过程中满足了某种条件导致线程必须中断,可以选择使用抛出运行级别异常来处理,如下:  
  <<  
          public   void   run()   {  
                if   (...)   throw   new   RuntimeException();  
          }  
  >>  
 
当线程代码抛出运行级别异常之后,线程会中断。:)这点java中解释得很清楚:  
  <<   @see   Thread  
  All   threads   that   are   not   daemon   threads   have   died,   either   by   returning   from   the   call   to   the   run   method   or   "by   throwing   an   exception   that   propagates   beyond   the   run   method".    
  >>  
 
但是对于invoke此线程的主线程会产生什么影响呢?主线程不受这个影响,不会处理这个RuntimeException,而且根本不能catch到这个异常。会继续执行自己的代码   :)  
 
所以得到结论:线程方法的异常只能自己来处理。  
   
 
关于最后一点,不相信的话大家可以做这么一个试验:  
  <<  
  public   class   TestThreadException   extends   Thread   {  
          public   void   run()   {  
                  throw   new   RuntimeException();  
          }  
   
          public   static   void   main(String[]   args)   throws   InterruptedException   {  
                  try   {  
                          new   TestThreadException().start();  
                  }   catch(RuntimeException   ex)   {  
                          //  
看看能不能到达这里?   :)  
                  }  
                   
                  Thread.sleep(1000);  
                  //  
看看能不能到达这里?   :)  
          }  
  }  
  >>  
结果当然是捕捉不到异常了。

记不得在哪里看到的代码,可以处理到线程中抛出的RuntimeException  
   
  public   class   ApplicationLoader   extends   ThreadGroup  
  {  
          private   ApplicationLoader()  
          {  
   
                  super("ApplicationLoader");  
   
          }  
   
          public   static   void   main(String[]   args)  
          {  
   
                  Runnable   appStarter   =   new   Runnable()  
                  {  
   
                          public   void   run()  
                          {  
                                  //invoke   your   application   (i.e.MySystem.main(args)  
   
                                  throw   new   NullPointerException();   //example,   throw   a   runtime   exception  
                          }  
                  };  
   
                  new   Thread(new   ApplicationLoader(),   appStarter).start();  
          }  
   
          //We   overload   this   method   from   our   parent  
          //ThreadGroup   ,   which   will   make   sure   that   it  
          //gets   called   when   it   needs   to   be.     This   is    
          //where   the   magic   occurs.  
          public   void   uncaughtException(Thread   thread,   Throwable   exception)  
          {  
                  //Handle   the   error/exception.  
                  //Typical   operations   might   be   displaying   a  
                  //useful   dialog,   writing   to   an   event   log,   etc.  
   
                  exception.printStackTrace();//example,   print   stack   trace  
          }  
  }  


呵呵,uncaughtException好像是唯一能够处理线程抛出的uncaught异常的入口。看来还是有细心人啊。确实如此,通过ThreadGroupuncaughtException方法还是有处理的机会。当线程抛出uncaughtException的时候,JVM会调用ThreadGroup的此方法。默认的处理如下:  
  <<  
          public   void   uncaughtException(Thread   t,   Throwable   e)   {  
  if   (parent   !=   null)   {  
          parent.uncaughtException(t,   e);  
  }   else   if   (!(e   instanceof   ThreadDeath))   {  
          e.printStackTrace(System.err);  
  }  
          }  
  >>  
 
每个Thread都会有一个ThreadGroup对象,可以通过Thread.getThreadGroup()方法得到,提供了上述默认的uncaught异常处理方法。  
 
上面没有提这点,因为俺认为在正常的情况下,这个方法的处理情况就已经足够了。还是那个线程设计的理念:线程的问题应该线程自己本身来解决,而不要委托到外部。通常情况下,外部不需要处理线程的异常。当然也有例外。:)  

 

 

以上是我在网上看到的一些资料,自己在做的时候没办法,只好设计静态变量了,(当然,用这种方法的前提是在主线程中加入thread.join()方法,那样主线程要等待子线程完成后再执行下一步,不然主线程都跑完了,子线程才出错,咋个都捕捉不到了)

 

程序也怪得很,竟然要求子线程抛异常后,要停掉主线程,也是没有现成的方法,最后自己定义的静态变量。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zichun921/article/details/5735309

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签