多線程解決excel數據多上傳問題

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章