java 多线程写excel_java通过poi上传excel表格并多线程批量插入数据到数据库

本文展示了如何使用Java的多线程和Apache POI库从Excel文件批量插入数据到数据库。通过创建线程池,根据数据量动态分配每个线程处理的数据量,并利用CountDownLatch同步线程,实现高效的数据导入。
摘要由CSDN通过智能技术生成

废话少说,直接上代码。

BaseMapper.xml

insert into base (name,password) values

(#{item.name},#{item.password})

select @@identity

BaseDao.java

public interface BaseDao {

/**

* 批量新增

* @param list

*/

public void batchInsert(List list);

}

BaseService.java

public interface BaseService{

/**

* 批量新增

* @param list

*/

public void batchInsert(List list);

}

BaseServiceImpl.java

@Service("baseService")

public class BaseServiceImpl implements BaseService{

@Autowired

private BaseDao baseDao;

@Override

public void batchInsert(List list) {

baseDao.batchInsert(list);

}

}

BaseController.java

/**

* 专门作测试用的Action类

* @author reyco

*

*/

@RequestMapping("base")

@Controller("baseController")

public class BaseController {

protected Logger logger = LoggerFactory.getLogger(getClass());

@Autowired

public BaseService baseService;

/**

* excel批量新增数据

* @param file

* @param request

* @return

* @throws IOException

*/

@ResponseBody

@RequestMapping("batchInsert")

public String batchInsert(@RequestParam("file")CommonsMultipartFile file,HttpServletRequest request) throws IOException {

//读取流

InputStream is = file.getInputStream();

//根据is流创建wb

HSSFWorkbook wb = new HSSFWorkbook(is);

//获取页

HSSFSheet sheet = wb.getSheetAt(0);

if(sheet != null) {

//过滤表格数据到List集合

List baseList = filterSheet(sheet);

//保存/提交数据

saveBaseInfoList(baseList);

return JSONResult.create("上传成功").toJSON();

}

return JSONResult.failCreate("上传失败", "").toJSON();

}

/**

* 读取表格数据加入到List容器

* @return

*/

private List filterSheet(HSSFSheet sheet){

// 作返回值

List list = null;

// 为null直接返回

if(null != sheet) {

list = new ArrayList();;

//循环读取表格数据

for(int i=1;ilist) {

int listSize = list.size();// 数据集合大小

int count =999; // 一个线程处理多少条数据,默认1000

//根据数据量确定一个线程处理多少条数据

if( listSize >= 1 && listSize < 1000) {

count = 333;

}else if(listSize >= 1000 && listSize < 10000) {

count = 1333;

}else if(listSize >= 10000) {

count = 5333;

}

int runThreadSize = (listSize / count) + 1; // 开启的线程数

logger.error("--------runThreadSize-------====="+runThreadSize);

List newList = null;// 存放每个线程的执行数据

ExecutorService executor = Executors.newFixedThreadPool(runThreadSize);// 创建一个线程池,数量和开启线程的数量一样

// 创建两个个计数器

CountDownLatch begin = new CountDownLatch(1);

CountDownLatch end = new CountDownLatch(runThreadSize);

// 循环创建线程

for (int i=0;inewList, CountDownLatch begin,CountDownLatch end) {

BatchInsertThread batchinsertThread = new BatchInsertThread(newList,begin,end);

new Thread(batchinsertThread).start();

}

}

BatchInsertThread.java

/**

* batchInsert线程类

* @author reyco

*

*/

public class BatchInsertThread implements Runnable{

protected Logger logger = LoggerFactory.getLogger(getClass());

private BaseService baseService = SpringContextHolder.getBean("baseService");

List list;

CountDownLatch begin;

CountDownLatch end;

public BatchInsertThread() {

}

public BatchInsertThread(List list, CountDownLatch begin, CountDownLatch end) {

this.list = list;

this.begin = begin;

this.end = end;

}

@Override

public void run() {

try {

baseService.batchInsert(list);

//执行完让线程直接进入等待

begin.await();

}catch (Exception e) {

logger.error(e.getMessage(),e);

}finally {

//这里要主要了,当一个线程执行完了计数要减一不要这个线程会被一直挂起

//,end.countDown(),这个方法就是直接把计数器减一的

end.countDown();

}

}

}

关于一点题外话,SpringContextHolder是小编写的一个获取spring管理bean的util类,需要了解的兄弟可以浏览我的另一篇博客:

简单获取Spring管理的bean

小编经过测试:  1万条数据内大约需要2s以内,10万条数据大约需要5s以内。更多数据小编没测试试过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值