• 技术文章 >Java >java教程

    Java实例详解之子线程任务异常,主线程事务回滚

    长期闲置长期闲置2022-05-09 17:49:49转载712
    本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于子线程任务发生异常时,主线程事务如何回滚的相关问题,包括了异常的捕获和事务的回滚等内容,下面一起来看一下,希望对大家有帮助。

    推荐学习:《java视频教程

    一、提出问题

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

    二、主线程与子线程

    先来看看基础,下图体现了两种线程的运行方式,

    在这里插入图片描述

    对于上文中提出的问题,一定是第二种才能解决主线程能够捕获子线程执行过程中发生的异常。这里就不得不提一个面试题,实现线程的两个接口Callable与Runnable之间的区别:

    public interface Callable<V> {
        V call() throws Exception;}
    public interface Runnable {
        public abstract void run();}

    可以看到call方法带返回值,run方法没有返回值。另外call方法可以抛出异常,run方法不可以。很明显,我们为了要捕获或得知子线程的运行结果,或者运行异常,都应该通过Callable接口来实现。

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

    public class ExpSubThread implements Callable {
        @Override
        public Object call() throws Exception {
            throw new NullPointerException();
        }}

    三、线程池

    在面临线程任务时,通常我们会预先建立一个线程池,线程池是预先规划好的n个线程资源的集合。它的好处在于:

    常用的线程池有两种,一种是JDK自带的,一种是Spring线程池,在Spring环境下后者常常被使用,二者大同小异。这里我们使用Spring API来构建一个线程池。

    public ThreadPoolTaskExecutor getThreadPool(){
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setMaxPoolSize(100);  //线程池最大线程数
            executor.setCorePoolSize(50);//线程池核心线程数
            executor.setQueueCapacity(50);//任务队列的大小
            executor.setThreadNamePrefix("test_"); //线程前缀名
            executor.initialize(); //线程初始化
            return executor;}

    四、异常的捕获

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

    @Testvoid subThreadExceptionTest() {
            try{
                //新建子线程对象
                ExpSubThread expSubThread = new ExpSubThread();
                //构建线程池
                ThreadPoolTaskExecutor executor = getThreadPool();
                //提交子线程任务,submit方法
                Future future = executor.submit(expSubThread);
                //在这里可以做主线程的业务其他流程操作
                //阻塞等待子线程的执行结果
                Object obj = future.get();  
            }catch (Exception e){
                e.printStackTrace();
                //事务回滚
            }}

    这里需要注意的是使用submit方法提交子线程任务到线程池内执行。ThreadPoolTaskExecutor有两种执行线程任务的方法,一种是execute方法,一种是submit方法。

    在这里插入图片描述

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

        V get() throws InterruptedException, ExecutionException;

    下面这张图是上面的测试用例程序程序e.printStackTrace();的效果,从图中可以看到两个Exception异常,一个是我们在子线程任务中以模拟的方式主动抛出的空指针异常,另一个由于空指针引发的get方法抛出的ExecutionException。

    在这里插入图片描述

    五、事务的回滚

    上文中大家已经看到我们通过

    那么既然我们已经可以在主线程内感知或catch子线程的异常信息了,下一步主线程的事务回滚是不是就太简单了?

    推荐学习:《java视频教程

    以上就是Java实例详解之子线程任务异常,主线程事务回滚的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:CSDN,如有侵犯,请联系admin@php.cn删除
    专题推荐:java
    上一篇:Java数组知识点(总结分享) 下一篇:一起来分析java是值传递还是引用传递
    20期PHP线上班

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• Java归纳总结之数组详解• 完全掌握JavaScript运行机制及原理• Java经典技巧之实现多线程、线程同步• Java设计模式解析之适配器模式(实例详解)• JavaScript经典基础详解之函数
    1/1

    PHP中文网