`
goycejin
  • 浏览: 8588 次
  • 性别: Icon_minigender_2
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Java中主线程如何捕获子线程抛出的异常

阅读更多
这么来看待这个问题。首先明确线程代码的边界。其实很简单,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异常的入口。看来还是有细心人啊。确实如此,通过ThreadGroup的uncaughtException方法还是有处理的机会。当线程抛出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异常处理方法。  
  上面没有提这点,因为俺认为在正常的情况下,这个方法的处理情况就已经足够了。还是那个线程设计的理念:“线程的问题应该线程自己本身来解决,而不要委托到外部。”通常情况下,外部不需要处理线程的异常。当然也有例外。:)  
分享到:
评论

相关推荐

    子线程任务发生异常,主线程事务如何回滚

    在 Java 中,存在两种线程模型:主线程和子线程。主线程是程序的入口点,而子线程是由主线程创建的辅助线程。子线程的运行结果可以通过阻塞的方式来获取。在 Java 中,我们可以使用 Callable 或 Runnable 接口来实现...

    java多线程编程之捕获子线程异常示例

    当子线程抛出一个未捕获的Unchecked异常时,子线程会立即停止执行,但不会影响主线程或其他子线程。在这种情况下,如果不进行特殊处理,异常的信息可能会丢失,导致调试困难。 Java提供了一个机制来捕获并处理子...

    基于Java子线程中的异常处理方法(通用)

    如果子线程发生了异常,get()方法将抛出ExecutionException异常,可以在父线程中捕获和处理。 结论 在Java子线程中处理异常是一个复杂的问题,但通过使用try ... catch ...、设置异常处理器和使用Future和Callable...

    android中UI主线程与子线程深入分析

    因此,Android系统规定,只有主线程才能修改UI组件,否则会抛出`CalledFromWrongThreadException`异常。 为了解决这个问题,开发者通常会在后台创建子线程进行耗时操作,然后通过消息传递机制与主线程通信。这里最...

    详解Java中多线程异常捕获Runnable的实现

    在 Java 多线程编程中,子线程抛出的异常不会被主线程捕获,这使得我们很难对子线程的异常进行捕获和处理。因此,我们需要实现主线程对子线程异常的捕获。 二、工具 为了实现多线程异常捕获,我们需要使用以下工具...

    android里如何在子线程中如何更新主线程的控件

    这意味着,如果你在子线程中尝试修改任何UI元素,如文本、图片或者布局,系统会抛出`android.os.NetworkOnMainThreadException`异常,提示你在子线程中进行了网络操作或者UI更新。因此,要在子线程中更新主线程的...

    java多线程中的异常处理机制简析

    然而,对于Unchecked异常,由于它们在运行时才抛出,线程可以不进行处理,此时线程会突然终止,但不会影响其他线程的执行,主线程或其他线程无法直接捕获到这个异常。 为了应对这种情况,Java提供了线程未捕获异常...

    一个线程oom会影响其他线程吗1

    这意味着,主线程抛出异常退出了,子线程仍然可以继续运行。然而,如果子线程是守护线程,那么子线程会随着主线程结束而结束。 结论 一个线程抛出 OOM 异常不会影响其他线程的运行。主线程和子线程之间的关系是平...

    17.Handler消息传递机制

    但这里有一个问题,Android不允许在非主线程中直接修改UI,因此这段代码会抛出`android.os.NetworkOnMainThreadException`异常,导致程序崩溃。 正确的做法是使用Handler来处理子线程与主线程的通信。Handler通常...

    模拟平抛运动。两个不同颜色的球,一个球自由落下,一个球同时水平抛出,两者同时落地。

    主线程可能负责更新场景,而两个子线程分别控制自由落体和水平抛出的球。每个球的线程内部会有循环,根据物理学公式计算球的新位置,并将这些信息反馈给主视图进行渲染。Java提供了`Thread`类和`Runnable`接口来实现...

    Android开发中多线程与UI更新.docx

    如果尝试在子线程中直接更新UI,应用会抛出异常。 3. **避免长时间阻塞**:主线程不应执行耗时操作,如网络请求、数据库操作等。这是因为主线程的阻塞会导致应用无响应(ANR),严重影响用户体验。根据Android规范,...

    JAVA100例之实例62JAVA多线程

    主线程不会捕获子线程抛出的异常,因此在子线程中需要妥善处理异常,避免程序意外终止。 总的来说,"JAVA100例之实例62JAVA多线程"实例将涵盖Java多线程的基础知识,包括创建线程、线程同步、线程通信、线程池以及...

    Java并发包之CountDownLatch用法.docx

    - **异常处理**:为了确保即使在子线程抛出异常时也能正确地调用`countDown()`,通常将`countDown()`放入`try...finally`块中。 - **超时等待**:可以通过`latch.await(timeout, unit)`设置等待的最长时间,如果超时...

    最新java ITAT预赛试题

    `Tux`类的`sName`被主线程和子线程共享,`piggy()`方法改变了`sName`,但不会影响到主线程中的`sName`,因为线程间的共享不是实时同步的。因此,输出结果是`vandeleur`,因为`run()`方法内的循环并未执行。 2. **...

    java高并发1

    但如果调用interrupt(),线程会抛出InterruptedException,此时需要捕获并处理这个异常。注意,中断线程时应判断并调用被阻塞线程的interrupt()方法,而非调用等待线程的。 线程的结束方式: 1. 通过共享变量(标志...

    JavaJs.zip

    当JavaScript抛出异常时,需要捕获并适当地处理,同时记录相关信息,以便于后续的问题排查。 10. **更新和维护**: 由于JavaScript和Java版本的更新,以及Android系统的迭代,开发者需要持续关注兼容性问题,及时...

    java线程编程

    如果主线程创建了一个子线程,子线程的未捕获异常不会直接影响主线程,但可以通过`Thread.UncaughtExceptionHandler`接口自定义处理子线程的未捕获异常。 总的来说,“Java线程编程”涵盖了线程的创建、启动、同步...

    java课程设计 多线程设计 内含源代码 打包发布

    主线程可能需要捕获子线程抛出的异常,可以通过`Thread.UncaughtExceptionHandler`进行设置。 9. **线程状态**: Java中的线程有新建、可运行、运行、阻塞、等待、超时等待和终止七种状态。理解这些状态转换有助于...

    Java软件开发实战 Java基础与案例开发详解 12-2 线程的生命周期 共10页.pdf

    如果线程在调用`wait()`、`sleep()`或`join()`方法时被中断,则会抛出InterruptedException异常。 #### 示例:控制线程状态 假设我们需要实现一个简单的场景,其中一个线程需要先执行,然后再执行另一个线程,最后...

Global site tag (gtag.js) - Google Analytics