excel名单人数过多,超多140000条,单个线程处理问题,已经不能满足需求,需要做多线程的优化。再一点就是多个线程导入需要给是否导入成功的标志。

首先,上传excel根据业务校验excel,这个部分省略,可以查上传excel和校验的相关知识。
其次,就是怎么将整个excel分拆成各个小的部分,然后分线程上传。

A、将excel全部加载在内存list中(batchParams)

//存储返回导入成功的条数
int countSuceeNumber=0;
//将全部excel记录发送多线程线程方法,批量导入数据
try{
countSuceeNumber=saveBaseInfoList(batchParams);
}catch(Exception e){
e.printStackTrace();
}

B、定义方法,多线程将excel的数据存储起来

/**
* 多线程批量存储数据
* @param batchParams
* @return
*/
public int saveBaseInfoList(List batchParams){
int count=999;//根据数量确定一个线程处理多少条数据
int listSize=batchParams.size();
if(listSize>=1 && listSize<1000){
count=333;
}else if(listSize>=1000 && listSize<10000){
count=1333;
}else if(listSize>=10000 && listSize<30000){
count=2333;
}else if(listSize>=30000){
count=3333;
}
//计算开启的线程数
int runThreadSize=(listSize/count)+1;
logger.info("开启的线程数量"+runThreadSize);
//存放每个线程的执行数据
List newList=null;
//创建一个线程池,数量和开启线程数一样
ExecutorService executor=Executors.newFixedThreadPool(runThreadSize);
//存放返回结果集
int successCountNumber=0;
//定义completionService
CompletionService<Integer> completionService=new ExecutorCompletionService<Integer>(executor);
try{
//循环创建线程
for(int i=0;i<runThreadSize;i++){
if((i+1)==runThreadSize){
int startIndex;
startIndex=(i*count);
int endIndex=listSize;
newList=batchParams.subList(startIndex, endIndex);
}else{
int startIndex=(i*count);
int endIndex=((i+1)*count);
newList=batchParams.subList(startIndex, endIndex);
}
createBatchInsertThread(completionService,newList);
}
//采用completionService.take(),内部维护阻塞队列,任务先完成的先获取到
for(int i=0;i<runThreadSize;i++){
Integer counts=completionService.take().get();
successCountNumber+=counts;
}
logger.info("成功的条数"+successCountNumber);
}catch(Exception e){
e.printStackTrace();
}finally{
executor.shutdown();
}
return successCountNumber;
}

C、调用多线程的执行类

private  Future<Integer> createBatchInsertThread(CompletionService<Integer> completionService,List newList) throws Exception{
BatchInsertThread batchinsertThread=new BatchInsertThread(newList);
@SuppressWarnings("unchecked")
Future<Integer> submit = completionService.submit(batchinsertThread);
return submit;
}

D、callable()的具体执行类

public class BatchInsertThread implements Callable<Integer>{


private BaseService baseService = (BaseService) SpringContextHolder.getApplicationContext().getBean("baseService");
private Logger logger = Logger.getLogger(getClass());
List list;

public BatchInsertThread(){

}

public BatchInsertThread(List list){
this.list=list;

}

@Override
public Integer call() throws Exception {
try{
logger.info("本次导入人数的大小"+list.size());
baseService.batchInsert(list);
}catch(Exception e){
e.printStackTrace();
logger.error(e.getMessage());
}
return list.size();
}

}

E、具体的业务执行类

@Service
public class BaseServiceImpl implements BaseService{

@Resource
private IAthleteScoreDao athleteScoreDao;

@Override
public void batchInsert(List list) throws Exception{
Map<String, Object>[] paramArrayOfMap=(Map[])list.toArray(new HashMap[list.size()]);
athleteScoreDao.batchAddAthleteScore(paramArrayOfMap);
}

}

这样整个过程执行下来,读取并把合格的excel存储起来,非常的快速。