newFixedThreadPool线程池实现多线程
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());
//不加这个会导致线程不安全,丢失数据
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("数据第几条:" + j);
//校验物料、供应商、ou、地点信息是否存在
packageAgreementService.checkMultiData(packageAgreementList.get(j), j ,user, dateFormat, errorList2, entityList);
semaphore.release();
} catch (ParseException e) {
e.printStackTrace();
}
});
}
//每隔10s检测线程是否执行结束
boolean flag = touchWorker.awaitTermination(10, TimeUnit.SECONDS);
if(!flag){
logger.info("一揽子协议价格录入完成!");
}
需要注意的问题点,多线程处理List数据可能发生线程不安全,
引入CopyOnWriteArrayList,Semaphore解决,或者加锁解决问题;所有线程执行完毕后再进行后续业务的处理,引入awaitTermination()方法。
发现上述逻辑有问题,被其他资料误导,awaitTermination并不是上述描述的作用。为了保证线程池的所有线程执行完毕,优化后代码如下:文章来源:https://www.toymoban.com/news/detail-667264.html
AtomicInteger count = new AtomicInteger();
/**
* 采用线程池处理数据,减少时耗,线程池数量为10
*/
int threadNum = 10;
ExecutorService touchWorker = Executors.newFixedThreadPool(threadNum);
Semaphore semaphore = new Semaphore(threadNum);//定义几个许可
for(TeamWorkMainConfirmInfoDto confirmInfoDto:list){
semaphore.acquire();
touchWorker.execute(()->{
try {
//根据主表id查询要导出的子流程信息
List<TeamWorkInfoExportDto> slaveInfoDtoList = teamWorkSlaveInfoService.findExportSlaveListByMainId(confirmInfoDto.getId());
lock.lock();
if(slaveInfoDtoList != null && slaveInfoDtoList.size() >0){
for(TeamWorkInfoExportDto slaveInfoDto:slaveInfoDtoList){
exportList.add(slaveInfoDto);
}
}else{ //如果没有子流程数据,添加主流程数据到导出数据中
TeamWorkInfoExportDto mainDto = new TeamWorkInfoExportDto();
mainDto.setTaskBookName(confirmInfoDto.getTaskBookName());
exportList.add(mainDto);
}
count.getAndIncrement();
logger.info("第" + count + "条数据!");
lock.unlock();
semaphore.release();
} catch (Exception e){
e.printStackTrace();
}
});
}
//判断所有线程是否都执行完
//EndTask endTask = new EndTask(list.size());
//touchWorker.execute(endTask);
while(true) {
if(list.size() == count.intValue()) {
logger.info("研发任务书多线程导出完成!");
break;
}else {
logger.info("研发任务书导出线程池的任务没有完成,等待。。。");
Thread.sleep(1000);
}
}
touchWorker.shutdown();
count 未使用静态变量的原因:使用static静态变量还需要在线程池结束后初始化,而且可能出现多用户竞争资源的现象导致出现问题。而且AtomicInteger 能有效保证原子性(用于后续验证所有线程执行完成)文章来源地址https://www.toymoban.com/news/detail-667264.html
到了这里,关于java 线程池实现多线程处理list数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!