最近开发商品同步功能。遇到 java.lang.OutOfMemoryError: Java heap space 问题,
在本机和同事电脑上跑程序,都没问题。30w条数据,单线程跑大概2个小时跑完。但是放到服务器上面跑 就挂了。每次在服务器上跑到大概 1/3的时候就抛出 java.lang.OutOfMemoryError: Java heap space 异常!
同步打代码如下:
public boolean syncProd2GoodsCallBack(List goodsCeneterProdVoList) {
if(goodsCeneterProdVoList != null && goodsCeneterProdVoList.size() > 0){
// 取出所有商品ID
List goodsIds = new ArrayList<>();
goodsCeneterProdVoList.stream().forEach(vo->{
goodsIds.add(vo.getProdId());
});
// 获取已存在的商品列表
List existList = tbGoodsMapper.getExistGoodsList(goodsIds);
Map existGoodsMap = existList.stream().collect(Collectors.toMap(TbGoods::getGoodsId, Function.identity(), (key1, key2) -> key2));
//获取已存在的图片列表
List existPicList = tbGoodsPictureMapper.getExistPictureList(goodsIds);
Map existPicMap = existPicList.stream().collect(Collectors.toMap(TbGoodsPicture::getGoodsPictureId,Function.identity(), (key1, key2) -> key2));
// 图片list
List pictureList = new ArrayList<>();
List goodsList = goodsCeneterProdVoList.stream().map(goodsCeneterProdVo -> {
TbGoods goods = existGoodsMap.get(goodsCeneterProdVo.getProdId());
if(BeanUtil.isEmpty(goods)){
goods = new TbGoods();
}
BeanUtil.copyPropertiesIgnoreNull(goodsCeneterProdVo,goods);
goods.setGoodsId(goodsCeneterProdVo.getProdId());
goods.setPlatformAuthFlag(StrUtil.isEmpty(goods.getPlatformAuthFlag()) ? "0" :goods.getPlatformAuthFlag() );
goods.setApprovalNumber(StrUtil.isEmpty(goods.getApprovalNumber())?" ":goods.getApprovalNumber());
List pictures = goodsCeneterProdVo.getProdPictureList();
// 每个商品的图片数据
List picList;
if(pictures !=null && pictures.size() > 0){
picList = pictures.stream().map(picVo->{
TbGoodsPicture picture = existPicMap.get(picVo.getProdPictureId()) ;
if(BeanUtil.isEmpty(picture)){
picture = new TbGoodsPicture();
}
BeanUtil.copyPropertiesIgnoreNull(picVo,picture);
picture.setGoodsId(picVo.getProdId());
picture.setGoodsPictureId(picVo.getProdPictureId());
return picture;
}).collect(Collectors.toList());
pictureList.addAll(picList);
picList.clear();
}
pictures.clear();
return goods;
}).collect(Collectors.toList()) ;
if(goodsList != null && goodsList.size() > 0){
tbGoodsMapper.saveOrUpdateBatch(goodsList);
}
if(pictureList !=null && pictureList.size() > 0){
tbGoodsPictureMapper.saveOrUpdateBatch(pictureList);
}
// 使用完之后 及时释放
goodsList.clear();
pictureList.clear();
existList.clear();
existGoodsMap.clear();
existPicList.clear();
existPicMap.clear();
goodsIds.clear();
}
return true;
}
纠结了很久,一点点的优化 ,从开始在遍历里面查询单个商品是否存在,到先把所有存在商品查出来,到从list查找换成map查找。到最后,每个list 和map使用完之后就clear掉。都不行!
部署到服务器跑到 1/3左右就挂了。
后来 我组长将 .stream().map()..collect(Collectors.toList()) 换成** .forEach() **,再放到服务器上居然跑成功了。修改后的代码如下:
public boolean syncProd2GoodsCallBack(List goodsCeneterProdVoList) {
if(goodsCeneterProdVoList != null && goodsCeneterProdVoList.size() > 0){
// 取出所有商品ID
List goodsIds = new ArrayList<>();
goodsCeneterProdVoList.stream().forEach(vo->{
goodsIds.add(vo.getProdId());
});
// 获取已存在的商品列表
List existList = tbGoodsMapper.getExistGoodsList(goodsIds);
Map existGoodsMap = existList.stream().collect(Collectors.toMap(TbGoods::getGoodsId, Function.identity(), (key1, key2) -> key2));
//获取已存在的图片列表
List existPicList = tbGoodsPictureMapper.getExistPictureList(goodsIds);
Map existPicMap = existPicList.stream().collect(Collectors.toMap(TbGoodsPicture::getGoodsPictureId,Function.identity(), (key1, key2) -> key2));
// 图片list
List pictureList = new ArrayList<>();
List goodsList = new ArrayList<>();
goodsCeneterProdVoList.forEach(goodsCeneterProdVo->{
TbGoods goods = existGoodsMap.get(goodsCeneterProdVo.getProdId());
if(BeanUtil.isEmpty(goods)){
goods = new TbGoods();
}
BeanUtil.copyPropertiesIgnoreNull(goodsCeneterProdVo,goods);
goods.setGoodsId(goodsCeneterProdVo.getProdId());
goods.setPlatformAuthFlag(StrUtil.isEmpty(goods.getPlatformAuthFlag()) ? "0" :goods.getPlatformAuthFlag() );
goods.setApprovalNumber(StrUtil.isEmpty(goods.getApprovalNumber())?" ":goods.getApprovalNumber());
List pictures = goodsCeneterProdVo.getProdPictureList();
// 每个商品的图片数据
List picList = new ArrayList<>();
if(pictures !=null && pictures.size() > 0){
pictures.forEach(picVo->{
TbGoodsPicture picture = existPicMap.get(picVo.getProdPictureId()) ;
if(BeanUtil.isEmpty(picture)){
picture = new TbGoodsPicture();
}
BeanUtil.copyPropertiesIgnoreNull(picVo,picture);
picture.setGoodsId(picVo.getProdId());
picture.setGoodsPictureId(picVo.getProdPictureId());
pictureList.addAll(picList);
});
picList.clear();
}
pictures.clear();
goodsList.add(goods);
});
if(goodsList != null && goodsList.size() > 0){
tbGoodsMapper.saveOrUpdateBatch(goodsList);
}
if(pictureList !=null && pictureList.size() > 0){
tbGoodsPictureMapper.saveOrUpdateBatch(pictureList);
}
// 使用完之后 及时释放
goodsList.clear();
pictureList.clear();
existList.clear();
existGoodsMap.clear();
existPicList.clear();
existPicMap.clear();
goodsIds.clear();
}
return true;
}
在此记录一下,可能原因:用stream().map()..collect(Collectors.toList()) 对内存消耗大一些!