zoukankan      html  css  js  c++  java
  • SpringBoot Test 多线程报错:dataSource already closed

    1:前言

    最近在项目中使用多线程对大任务拆分处理时,进行数据库操作的时候报错了。

    业务代码大概是这样的:

    @Service
    public calss TestServiceImpl implements TestService{
    	@Resource
    	private TestMapper testMapper;
    
    
    	public void insert(Test test){
    		ThreadPoolExecutor executor = new ThreadPoolExecutor(...);
    
    		executor.execute(() -> {
    			testMapper.insert(test);
    		});
    	}
    
    }
    

    测试用例代码:

    @RunWith(SpirngRunner.class)
    @SpringBootTest
    public class ApplicationTests{
    	
    	@Resource
    	private TestService testService;
    
    	@Test
    	public void insertTest(){
    		Test test = new Test();
    		testService.insert(test);
    	}
    
    }
    

    2:排查思路

    1:项目中使用了一个很老旧的定时器工具(LTS),由于配置未接入,启动时LTS一直会报错的,

    我首先怀疑是LTS的问题,是不是内部某部分源码调用了DruidDataSource的close方法。
    因此我在项目中先把LTS排除不让它启动。

    结果:然并卵

    2:后来怀疑是不是项目中的定时任务造成的,因为数据源关闭前打印了以下日志

    可以看到 Thread-2 执行了ThreadPoolTaskExecutor 再关闭数据源的。
    因此我在SpringBoot 的启动类上加上了以下代码

    @SpringBootApplication(exclude = {TaskExecutionAutoConfiguration.class})
    

    结果:然并卵

    3:关电脑回家吃饭睡觉

    第二天早上回到工位上缓了一会,思考还有什么原因会导致这种问题。
    因为我们的线程池是一个封装的工具类封装过的(我封装的),里面有两行代码引起了我的注意:

    我先把 threadPoolExecutor.awaitTermination(3, TimeUnit.MINUTES); 这行代码注释掉,重新跑测试用例。

    发现并没有报错,并且程序很快就终止运行了。
    在这里我就想到了,SpringBoot Test 中主线程突出,是不会管用户线程是否结束了任务的这个问题。

    3:根本原因

    1:SpringBoot Test 主线程退出,导致Spring 容器关闭。
    2:Spring容器关闭,导致DruidDataSource 关闭
    3:此时用户线程去访问已关闭的数据源,导致报错。

    这样不行啊,那我测试用例怎么跑完呢?
    可能这个时候有人会想到在测试用例最后面加以下代码:

    TimeUnit.SECONDS.sleep(30);

    可是本人觉得不够优雅,也不灵活。

    4:解决方案

    监听容器关闭,关闭前先判断线程池中是否存在未执行玩任务的线程。

    ThreadPoolExecutor 的源码:

    因此我们是可以知道是否存在未执行完任务的线程的。

    所以我在项目中写了以下代码:

    当线程池中存在未执行完任务的线程的时候,就先等待,直到所有任务完成或超过等待时间。

    可把自己牛逼坏了(叉会腰)!

  • 相关阅读:
    HDU5597/BestCoder Round #66 (div.2) GTW likes function 打表欧拉函数
    HDU5596/BestCoder Round #66 (div.2) 二分BIT/贪心
    HDU 5596/BestCoder Round #66 (div.2) GTW likes math 签到
    BZOJ 1877: [SDOI2009]晨跑 费用流
    BZOJ 1452: [JSOI2009]Count 二维树状数组
    BZOJ 1143 1143: [CTSC2008]祭祀river 最长反链
    Codeforces Round #335 (Div. 2) D. Lazy Student 贪心
    Codeforces Round #335 (Div. 2) C. Sorting Railway Cars 连续LIS
    Codeforces Round #335 (Div. 2) A. Magic Spheres 模拟
    UVALive 6187 Never Wait for Weights 带权并查集
  • 原文地址:https://www.cnblogs.com/zgq7/p/13994891.html
Copyright © 2011-2022 走看看