newFixedThreadPool線程池實現(xiàn)多線程
List<PackageAgreementEntity> entityList = new CopyOnWriteArrayList<>();
//多線程 10個線程
//int threadNum = 10;
int listSize = 300;
List<List<PackageAgreementDto>> splitData = Lists.partition(packageAgreementList, listSize);
//CountDownLatch latch = new CountDownLatch(splitData.size());
//聲明線程池對象
ExecutorService touchWorker = Executors.newFixedThreadPool(splitData.size());
//不加這個會導致線程不安全,丟失數(shù)據(jù)
Semaphore semaphore = new Semaphore(splitData.size());//定義幾個許可
List<PackageAgreementErroDto> errorList2 = new CopyOnWriteArrayList();
for (int i = 0; i < packageAgreementList.size(); i++) {
final int j = i;
semaphore.acquire();
touchWorker.execute(()->{
try {
logger.info(Thread.currentThread().getName()+ j);
logger.info("數(shù)據(jù)第幾條:" + j);
//校驗物料、供應商、ou、地點信息是否存在
packageAgreementService.checkMultiData(packageAgreementList.get(j), j ,user, dateFormat, errorList2, entityList);
semaphore.release();
} catch (ParseException e) {
e.printStackTrace();
}
});
}
//每隔10s檢測線程是否執(zhí)行結束
boolean flag = touchWorker.awaitTermination(10, TimeUnit.SECONDS);
if(!flag){
logger.info("一攬子協(xié)議價格錄入完成!");
}
需要注意的問題點,多線程處理List數(shù)據(jù)可能發(fā)生線程不安全,
引入CopyOnWriteArrayList,Semaphore解決,或者加鎖解決問題;所有線程執(zhí)行完畢后再進行后續(xù)業(yè)務的處理,引入awaitTermination()方法。
發(fā)現(xiàn)上述邏輯有問題,被其他資料誤導,awaitTermination并不是上述描述的作用。為了保證線程池的所有線程執(zhí)行完畢,優(yōu)化后代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-667264.html
AtomicInteger count = new AtomicInteger();
/**
* 采用線程池處理數(shù)據(jù),減少時耗,線程池數(shù)量為10
*/
int threadNum = 10;
ExecutorService touchWorker = Executors.newFixedThreadPool(threadNum);
Semaphore semaphore = new Semaphore(threadNum);//定義幾個許可
for(TeamWorkMainConfirmInfoDto confirmInfoDto:list){
semaphore.acquire();
touchWorker.execute(()->{
try {
//根據(jù)主表id查詢要導出的子流程信息
List<TeamWorkInfoExportDto> slaveInfoDtoList = teamWorkSlaveInfoService.findExportSlaveListByMainId(confirmInfoDto.getId());
lock.lock();
if(slaveInfoDtoList != null && slaveInfoDtoList.size() >0){
for(TeamWorkInfoExportDto slaveInfoDto:slaveInfoDtoList){
exportList.add(slaveInfoDto);
}
}else{ //如果沒有子流程數(shù)據(jù),添加主流程數(shù)據(jù)到導出數(shù)據(jù)中
TeamWorkInfoExportDto mainDto = new TeamWorkInfoExportDto();
mainDto.setTaskBookName(confirmInfoDto.getTaskBookName());
exportList.add(mainDto);
}
count.getAndIncrement();
logger.info("第" + count + "條數(shù)據(jù)!");
lock.unlock();
semaphore.release();
} catch (Exception e){
e.printStackTrace();
}
});
}
//判斷所有線程是否都執(zhí)行完
//EndTask endTask = new EndTask(list.size());
//touchWorker.execute(endTask);
while(true) {
if(list.size() == count.intValue()) {
logger.info("研發(fā)任務書多線程導出完成!");
break;
}else {
logger.info("研發(fā)任務書導出線程池的任務沒有完成,等待。。。");
Thread.sleep(1000);
}
}
touchWorker.shutdown();
count 未使用靜態(tài)變量的原因:使用static靜態(tài)變量還需要在線程池結束后初始化,而且可能出現(xiàn)多用戶競爭資源的現(xiàn)象導致出現(xiàn)問題。而且AtomicInteger 能有效保證原子性(用于后續(xù)驗證所有線程執(zhí)行完成)文章來源地址http://www.zghlxwxcb.cn/news/detail-667264.html
到了這里,關于java 線程池實現(xiàn)多線程處理list數(shù)據(jù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!