美文网首页
多线程的异常和事务

多线程的异常和事务

作者: 初心myp | 来源:发表于2019-07-30 16:36 被阅读0次

    子线程中的异常在主线程中是不可以catch的
    在spring中主线程有事务,那么子线程中有事务么?

    捕获异常

    我们使用多线程时,会涉及到某些线程执行失败了,而抛出异常,但是主线程却捕捉不到子线程的异常。这时候我们就要处理一下子线程的异常,然后让主线程捕获到。

    使用的是多线程的话:我们使用
    ThreadOperation threadOperation= new ThreadOperation();
    Thread innerThread = new Thread(threadOperation);
    innerThread.setUncaughtExceptionHandler(new ExceptionHandle());
    innerThread.start();
    可以通过上面的四行代码来捕获到异常

    具体代码如下:

    package com.chuxin.fight.demo.thread;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * @FileName: MutiThreadException
     * @Description: 多线程的异常处理
     * @author: <a href="***@163.com">myp</a>
     * @create: 2019-01-08 17:06
     */
    public class MutiThreadException {
        //https://blog.csdn.net/weijiaxiaobao/article/details/51217265
        public static void main(String[] args) {
            System.out.println("MutiThreadException.main()------>start<------");
            try {
                List<Future<Object>> resultList = new ArrayList<>();
                ExceptionHandle exceptionHandle = new ExceptionHandle();
                ExecutorService service=Executors.newFixedThreadPool(6);
                for (int i = 0; i < 3; i++) {
                    Thread t=new Thread(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("id "+Thread.currentThread().getName()+"---start>");
                            if(Thread.currentThread().getName().endsWith("2")){
    //                          int i=1/0;
                                throw new RuntimeException();
                            }
                            try {
                                Thread.sleep(3000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println("id "+Thread.currentThread().getName()+"----end:");
                        }
                    });
                    //不是用线程池执行线程,使用循环的方式创建多线程,那么就用下面这两行和ExceptionHandle类来捕获子线程中的异常
    //              t.setUncaughtExceptionHandler(new ExceptionHandle());
    //                t.start();
                    //使用线程池的方式执行线程,如果子线程有异常的话,ExecutorService就已经捕获到了,我们可以从future对象中获取异常。正常情况下future对象中获取的是null,有异常的话获取到的就是异常信息
                    Future<Object> future = (Future<Object>) service.submit(t);
                    resultList.add(future);
                }
                for(Future f:resultList){
                    //在这里遍历就可以获取到future里面的异常,如果获取到的是null就说明成功执行了,没有异常。这里使用future的get方法时必须使用try catch才能获取到future对象里面的异常
                    try {
                        Object o=f.get();
                        System.out.println(o);
                    } catch (Exception e) {
                        System.out.println(e.toString()+"===========================");
                    }
                }
                service.shutdown();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("MutiThreadException.main()------>end<------");
        }
    }
    
    
    package com.chuxin.fight.demo.thread;
    
    /**
     * @FileName: ExceptionHandle
     * @Description: ExceptionHandle
     * @author: <a href="mailto:***@163.com">myp</a>
     * @create: 2019-01-08 17:11
     */
    public class ExceptionHandle implements Thread.UncaughtExceptionHandler {
    
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("子线程的异常,通过主线程捕获到了");
        }
    }
    

    事务控制

    在事务内另起线程是实现不了的

    只有spring托管的bean才会去管理事务,自己new出来的不管理事务

    举个例子,如果我们多线程运行的任务是一个添加的方法,如果某个线程添加失败的时候,我们需要事务控制。

    如果我们在主线程上面直接使用注解@Transactional来控制事务是不好使的,我们需要控制的是子线程的事务,所以这里提供的解决办法就是,我们run方法里面调用的添加方法不放在当前类里面,放在其他的类里面,然后将那个类通过注入的方法注入到当前的类里面,然后通过那个类进行调用,这样事务就可以通过使用注解@Transactional来控制事务了。同样也就解释了上面红色字体的那句话,我们通过注入的方式来使用添加方法,那么那个类(也就是一个Bean)就交给spring托管了,这样spring就帮我们管理事务了。

    图例.png

    需要在B类里面的添加方法上面添加注解@Transactional

    相关文章

      网友评论

          本文标题:多线程的异常和事务

          本文链接:https://www.haomeiwen.com/subject/jmbnrctx.html