最近写的一个程序中一个地址处理的方法一直在获取registryTime 的时候莫名其妙的报错DataSource isclosed。
后发现SimpleDateFormat不是线程安全的,多线程时会报错很奇怪。甚至会直接停止了应用。
开始代码是这样的
@Async("addressTaskAsyncPool")
public void add2MetaAddress(List<Map> listMaps) {
log.debug("开始进入地址处理方法:");
//获取当前系统的地址模型
Model addressModel = modelMapper.selectByModelTypeAppId(ModelEnum.ADDRESSMODEL.ordinal(), appid);
String modelName = addressModel == null ? null : addressModel.getModelName();
if (!CollectionUtils.isEmpty(listMaps)) {
for (int i = 0; i < listMaps.size(); i++) {
Map map = listMaps.get(i);
Object obj = map.get(EsDataStructDefine.ES_REGISTRY_TIME);
Date registryTime = null;
if (obj != null) {
Long date = (Long) obj;
registryTime = DateUtil.formatDate(DateFormatUtils.format(date,FORMAT));
}
if (map.get(EsDataStructDefine.ES_STORE_ID) != null) {
Long id = Long.parseLong(map.get(EsDataStructDefine.ES_STORE_ID).toString());
String content = map.get(EsDataStructDefine.ES_CONTENT) == null ? "" : map.get(EsDataStructDefine.ES_CONTENT).toString();
if (content.isEmpty()) {
log.info("诉求内容为空,跳过当前诉求");
continue;
}
//保存地址和诉求内容作为训练样本
addAppealAddress(id, content, modelName, registryTime);
}
}
}
}
这里的时间转化就是因为这个方法是多线程,多以程序运行时到这里有会直接closed。
解决的方式有及每次使用时new 一个SimpleDateFormat,就不会在报错了。
@Async("addressTaskAsyncPool")
public void add2MetaAddress(List<Map> listMaps) {
log.debug("开始进入地址处理方法:");
//获取当前系统的地址模型
Model addressModel = modelMapper.selectByModelTypeAppId(ModelEnum.ADDRESSMODEL.ordinal(), appid);
String modelName = addressModel == null ? null : addressModel.getModelName();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (!CollectionUtils.isEmpty(listMaps)) {
for (int i = 0; i < listMaps.size(); i++) {
Map map = listMaps.get(i);
Object obj = map.get(EsDataStructDefine.ES_REGISTRY_TIME);
Date registryTime = null;
if (obj != null) {
Long date = (Long) obj;
String d = sdf.format(date);
registryTime = DateUtil.formatDate(d);
}
if (map.get(EsDataStructDefine.ES_STORE_ID) != null) {
Long id = Long.parseLong(map.get(EsDataStructDefine.ES_STORE_ID).toString());
String content = map.get(EsDataStructDefine.ES_CONTENT) == null ? "" : map.get(EsDataStructDefine.ES_CONTENT).toString();
if (content.isEmpty()) {
log.info("诉求内容为空,跳过当前诉求");
continue;
}
//保存地址和诉求内容作为训练样本
addAppealAddress(id, content, modelName, registryTime);
}
}
}
}
但是资源耗费厉害。
后来发现,java有比较成熟的处理日期各种格式转化的joda-time库,接口简单并且是线程安全的;
配置pom.xml
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.4</version>
</dependency>
long startTime = System.currentTimeMillis();
DateTime dt=new DateTime().withMillis(startTime);
Date dd = dt.toDate();
官网连接
http://www.joda.org/joda-time/userguide.html