java多线程操作mysql数据库使用cpu过高怎么解决?

qq_34403052 2017-07-10 05:26:19
在做多数据同步到mysql数据库时,由于单线程处理数据较慢,所以考虑用多线程。

这里大多数都是mysql
单独看下mysql的cpu可以达到80%多
代码如下:

public void saveAllSaleDetail(List<?> list) throws Exception {
Map<String, SaleDetailEntity> saleDetails = new HashMap<String, SaleDetailEntity>();
int batchSize=1000,
threadCounts=10;
if(list.size() >= batchSize){
ExecutorService exec=Executors.newCachedThreadPool();
List<Callable<Map<String, SaleDetailEntity>>> callList=new ArrayList<Callable<Map<String, SaleDetailEntity>>>();
int len=list.size()/threadCounts;
if(len==0){
threadCounts=list.size();
len=list.size()/threadCounts;
}
for(int i=0;i<threadCounts;i++){
final List<SaleDetailEntity> subList;
if(i==threadCounts-1){
subList=(List<SaleDetailEntity>) list.subList(i*len,list.size());
}else{
subList=(List<SaleDetailEntity>) list.subList(i*len, len*(i+1)>list.size()?list.size():len*(i+1));
}
callList.add(new Callable<Map<String, SaleDetailEntity>>(){
@Override
public Map<String, SaleDetailEntity> call() throws Exception {
Map<String, SaleDetailEntity> saleDetails = new HashMap<String, SaleDetailEntity>();
for (SaleDetailEntity saleDetail : subList) {
SaleDetailEntity sale = new SaleDetailEntity();
sale.setOrgId(saleDetail.getOrgId());
sale.setOwnerId(saleDetail.getOwnerId());
sale.setProofId(saleDetail.getProofId());
sale.setProofLines(saleDetail.getProofLines());
List<SaleDetailEntity> saleDetailList = saleDetailDao.selectAllSaleDetailList(sale);
if (saleDetailList != null && saleDetailList.size() > 0) {
SaleDetailEntity saleDetailEntity = saleDetailList.get(0);
String id = saleDetailEntity.getId();
saleDetail.setId(id);
saleDetailDao.updateSaleDetail(saleDetail);
} else {
String uuid = RandomParamUtil.getUuid();
saleDetail.setId(uuid);
saleDetails.put(saleDetail.getProofId(), saleDetail);
}

}
return saleDetails;
}
});
}
List<Future<Map<String,SaleDetailEntity>>> invokeAll = exec.invokeAll(callList);
exec.shutdown();
for (Future<Map<String, SaleDetailEntity>> future : invokeAll) {
Map<String, SaleDetailEntity> map = future.get();
if(!map.isEmpty()){
saleDetailDao.insertAllSaleDetail(map);
}
}

}else{
for (Object object : list) {
SaleDetailEntity saleDetail = (SaleDetailEntity) object;
// 判断是否为重复数据,是直接修改
SaleDetailEntity sale = new SaleDetailEntity();
sale.setOrgId(saleDetail.getOrgId());
sale.setOwnerId(saleDetail.getOwnerId());
sale.setProofId(saleDetail.getProofId());
sale.setProofLines(saleDetail.getProofLines());
List<SaleDetailEntity> saleDetailList = saleDetailDao.selectAllSaleDetailList(sale);
if (saleDetailList != null && saleDetailList.size() > 0) {
SaleDetailEntity saleDetailEntity = saleDetailList.get(0);
String id = saleDetailEntity.getId();
saleDetail.setId(id);
saleDetailDao.updateSaleDetail(saleDetail);
} else {
String uuid = RandomParamUtil.getUuid();
saleDetail.setId(uuid);
saleDetails.put(saleDetail.getProofId(), saleDetail);
}
}
if (saleDetails != null && saleDetails.size() > 0) {
saleDetailDao.insertAllSaleDetail(saleDetails);
}

}


try {
//sendMCSP((List<SaleDetailEntity>)list);
} catch (Exception e) {
logger.error(e);
}
}


...全文
3334 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_40852944 2018-06-21
  • 打赏
  • 举报
回复
1,Executors.newCachedThreadPool(); 这个可以改成固定线程Executors.newFixedThreadPool();固定线程数量
2,你的代码需要好好优化一下
我惠依旧 2018-05-23
  • 打赏
  • 举报
回复
4楼的够用了
dengbiliduo 2018-04-15
  • 打赏
  • 举报
回复
mybatis或者hibernate都可以批量插入的,你先循环放到list里面,再一起put进去,然后代码我觉得挺乱的,可以加个注释
qq_29628385 2018-02-05
  • 打赏
  • 举报
回复
能够直接用sql 查出来的逻辑为啥要在代码层面还要放在循环里,,,,你CPU不高才怪,连数据库查询最好别放在循环里
tlzjff 2017-08-01
  • 打赏
  • 举报
回复
数据库如果光insert,如果有自增列,cpu一般不会很高 数据库如果有大量查询,需要观察执行计划中的索引是否合理,如果不合理cpu可能会高 数据库如果数据较大,update时更新了非聚集索引,cpu也可能会上 如果后2种个假设全部成立,边查边更新边插入情况会更差 如果想不改造数据库现有情况下优化此问题的话,可以试试以下方案 1)最好先把你的执行语句都分析下,看看执行计划是否合理 2)数据先预处理一遍,先把要处理的数据先通过select比较后,归为update类型,insert类型(你可以定义2个list,一个后续做更新,一个后续做插入),记得使用有索引的列作为select的条件,看看dao里面的where语句是否合理,别让db有太多计算逻辑,只用索引做简单查询 3)如果执行计划合理,把更新、插入,分别作为2个线程模块,按步骤进行同类型的多线程操作,不同步骤之间不要同时进行交叉的多线程操作
Buguanjia-Ssj 2017-07-29
  • 打赏
  • 举报
回复
我只看到了循环里访问数据库,这种操作6666
qq_34403052 2017-07-11
  • 打赏
  • 举报
回复
多线程操作数据库太频繁 ,建议使用数据库负载均衡,读写分离
tianfang 2017-07-11
  • 打赏
  • 举报
回复
多线程插入不一定会快,会引起数据库加锁,而且还可能引起事务冲突导致锁表 多线程处理可能比单线程消耗更多的时间

25,988

社区成员

发帖
与我相关
我的任务
社区描述
高性能WEB开发
社区管理员
  • 高性能WEB开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧