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存儲起來,非常的快速。