java子线程异常抛出到主线程,java主线程捕获子线程异常

  java子线程异常抛出到主线程,java主线程捕获子线程异常

  本文给大家带来一些java的相关知识,主要介绍子线程任务异常时如何回滚主线程事务的相关问题,包括异常捕获和事务回滚。来看看吧,希望对你有帮助。

  如何解决写爬虫IP受阻的问题?立即使用。

  

一、提出问题

  主线程向线程池提交了一个任务,如果执行这个任务过程中发生了异常,如何让主线程捕获到该异常并且进行事务的回滚

  

二、主线程与子线程

  先来看看基础的。下图显示了这两个线程是如何运行的,

  左图是主线程启动一个子线程后,两个线程独立运行,互不干扰,生死有定数。从此你我就是路人!右图是主线程启动一个子线程后继续执行主线程的程序逻辑,子线程的执行结果是在某个节点阻塞得到的。

  对于上面提到的问题,主线程可以捕捉到子线程执行过程中发生的异常,这一定是解决问题的第二种方式。这里不得不提一个面试问题,来认识线程的可调用接口和可运行接口的区别:

  公共接口CallableV {

  V call()抛出异常;}公共接口Runnable {

  公共抽象void run();}可以看到call方法有返回值,run方法没有返回值。另外,call方法可以抛出异常,run方法不能。显然,为了捕获或知道子线程的运行结果,或者运行异常,我们都应该通过可调用接口来完成。

  这里我们写一个ExpSubThread类(子线程异常模拟类),实现可调用接口,不用做太多动作就直接抛出空指针异常。

  公共类ExpSubThread实现Callable {

  @覆盖

  公共对象调用()引发异常{

  抛出新的NullPointerException();

  }}

三、线程池

  面对线程任务时,我们一般会提前设置一个线程池。线程池是预先计划的N个线程资源的集合。其优点是:

  执行任务时,不会创建新线程,而是使用线程池中现有的线程资源。任务执行的完成不是销毁线程,而是将线程资源返回线程池。从而在一定程度上节省了线程创建和销毁所消耗的资源,达到了线程资源重用的目的。因为线程池创建的大小是有上限的,所以线程池的另一个作用就是避免无限创建线程和无限占用应用资源导致系统崩溃的问题。常用的线程池有两种,一种是JDK自带的,一种是Spring线程池。后者常用于春季环境,两者类似。这里我们使用Spring API来构建一个线程池。

  公共threadpooltasktexecutor getThreadPool(){

  threadpooltasktexecutor executor=new threadpooltasktexecutor();

  executor . setmaxpoolsize(100);//线程池中的最大线程数

  executor . setcorepoolsize(50);//线程池中的核心线程数

  executor . setqueuecapacity(50);//任务队列的大小

  executor . setthreadname prefix( test _ );//线程前缀名

  executor.initialize()。//线程初始化

  返回执行人;}

四、异常的捕获

  下面是我写的一个测试用例,这里代表了主线程的程序执行过程。

  @ test void subthreadexception test(){

  尝试{

  //创建新的子线程对象

  ExpSubThread ExpSubThread=new ExpSubThread();

  //建立一个线程池

  threadpooltasktexecutor executor=getThreadPool();

  //提交子线程任务,提交方法

  future future=executor . submit(expusubthread);

  //在这里可以操作主线程的其他业务流程。

  //阻塞并等待子线程的执行结果

  object obj=future . get();

  }catch(异常e){

  e . printstacktrace();

  //事务回滚

  }}这里需要注意的是,submit方法是用来将子线程任务提交给线程池执行的。ThreadPoolTaskExecutor有两个方法来执行线程任务,一个是execute方法,一个是submit方法。

  execute方法没有返回值,无法判断任务是否成功完成,对应的线程类实现Runnable接口。submit方法有一个返回值,返回一个Future,对应的thread类实现Callable接口。

  Future.get()方法达到阻塞主线程的目的,从而判断子线程任务的执行结果,get方法可以抛出异常。

  V get()抛出InterruptedException,ExecutionException下图是上面的测试用例程序e . printstacktrace();从图中可以看出,有两种异常异常,一种是我们在子线程任务中主动模拟抛出的空指针异常,另一种是空指针导致的get方法抛出的ExecutionException。

  

五、事务的回滚

  正如你在上面看到的,我们通过了。

  类实现可调用接口,达到获取线程返回值或异常抛出的目的。Submit可以将线程任务提交给线程池,并可以得到子线程执行结果的返回值Future。Future的get()方法可以获取子线程的执行信息,包括异常抛出。那么现在我们可以感知到主线程或者catch子线程的异常信息,那么下一步回滚主线程的事务是不是太简单了?

  使用spring环境中的@Transactional注释实现conn.rollback()的事务回滚。推荐:《java视频教程》以上是Java实例的子线程的任务异常和主线程的事务回滚的细节。更多详情请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: