场景:
在单元测试中开启子线程进行数据库的访问
问题描述
今天在单元测试里面准备测试多线程访问数据库的一个小demo,但是发现刚进入子线程里就结束了
private static SqlSession sqlSession;
private static InputStream in;
private static ThreadLocal<DateFormat> dateThreadLocal = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
}
};
static {
try {
in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
sqlSession = sessionFactory.openSession();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testUpdate(){
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
try {
System.out.println("进入线程中!~");
Date date = dateThreadLocal.get().parse("2022-3-5 23:56:27");
Emp emp = new Emp();
emp.setName("王老七");
emp.setUpdate_time(date);
int row = sqlSession.update("EmpMapper.update", emp);
sqlSession.commit();
System.out.println("更新成功! 影响行数: " + row);
sqlSession.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
});
executorService.shutdown();
原因分析:
最后发现原来是Junit单元测试是创建出来的子线程都是守护线程,在用户线程执行完毕以后JVM就直接退出了
解决方案:
解决方法 一 : 放在main函数中执行肯定没问题,因为main函数就是用户线程默认创建出来的子线程也是用户线程,jvm会等待所有用户线程执行完毕以后才会退出jvm,但是不会等守护线程(GC就是守护线程)
解决方法 二 : thread.join() 使用该方法通知主线程等待子线程执行完毕以后再结束
解决方法 三 : 同理给主线程添加耗时操作,Thread.sleep(1000);