我在使用Spring框架的项目中获得了一项服务。
public class MyServiceImpl implements IMyService {
public MyObject foo(SomeObject obj) {
MyObject myobj = this.mapToMyObject(obj);
myobj.setLastUpdatedDate(new Date());
return myobj;
}
private MyObject mapToMyObject(SomeObject obj){
MyObject myojb = new MyObject();
ConvertUtils.register(new MyNullConvertor(), String.class);
ConvertUtils.register(new StringConvertorForDateType(), Date.class);
BeanUtils.copyProperties(myojb , obj);
ConvertUtils.deregister(Date.class);
return myojb;
}
}
然后我有一个类在多线程中调用foo();
出现了问题。在某些线程中,我在调用
时出错 BeanUtils.copyProperties(myojb , obj);
说无法调用com.my.MyObject.setStartDate - java.lang.ClassCastException@2da93171
显然,这是由ConvertUtils.deregister(Date.class)
引起的,BeanUtils.copyProperties(myojb , obj);
应该在BeanUtils.copyProperties(myojb , obj);
之后调用。
看起来其中一个线程取消注册Date类,而另一个线程即将调用{{1}}。
所以我的问题是如何使私有方法mapToMyObject()线程安全?
或者只是在私有方法中使用时,简单地使BeanUtils线程安全。
如果我以这种方式保存代码,但问题仍然存在,而是在sevlet中调用这个foo()方法吗?如果许多sevlets同时调用,那么这也是一个多线程的情况吗?
答案 0 :(得分:4)
修改:已删除已同步的关键字,因为它不是必需的,请参阅下面的评论。
不使用BeanUtils类中的静态方法,而是使用私有BeanUtilsBean实例(http://commons.apache.org/proper/commons-beanutils/apidocs/org/apache/commons/beanutils/BeanUtilsBean.html)。这样,每次调用方法时都不需要注册/取消注册转换器。
public class MyServiceImpl implements IMyService {
private final BeanUtilsBean beanUtilsBean = createBeanUtilsBean();
private static BeanUtilsBean createBeanUtilsBean() {
ConvertUtilsBean convertUtilsBean = new ConvertUtils();
convertUtilsBean.register(new MyNullConvertor(), String.class);
convertUtilsBean.register(new StringConvertorForDateType(), Date.class);
BeanUtilsBean beanUtilsBean = new BeanUtilsBean(convertUtilsBean);
return beanUtilsBean;
}
public MyObject foo(SomeObject obj) {
MyObject myobj = this.mapToMyObject(obj);
myobj.setLastUpdatedDate(new Date());
return myobj;
}
private MyObject mapToMyObject(SomeObject obj){
MyObject myojb = new MyObject();
beanUtilsBean.copyProperties(myojb , obj);
return myojb;
}
}
答案 1 :(得分:0)
将同步块添加到代码的敏感部分或同步方法:
http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html