JAXB 线程安全问题解决办法
2015-01-14 09:00
337 查看
项目开发中涉及到对象与XML的转换,考虑到代码的简洁性,一直在使用java内置的JAXB来完成这项任务
一直在用的方法:
但在一个银行项目上线中发现,经常会发生ArrayIndexOutOfBoundsException,经过google一番搜索,发现问题在于marshaller的marshal方法不是线程安全的,而JAXBContext.newInstance()是线程安全的。为了解决这一问题,需要将代码进行改造
为了尽量少的重复创建marshaller对象(创建marshaller对象的操作官方认为是比较耗CPU的)这里使用对象池的概念,开发包使用commons-pool,这里用到了KeyedObjectPool
在使用时应该注意borrowObject并使用完成后一定要记得returnObject,这样才能达到对象池的效果
一直在用的方法:
static Map<String,Marshaller> mars static Map<String,Unmarshaller> umars这样做的好处是对于相同的类名,不用重复创建marshaller。
但在一个银行项目上线中发现,经常会发生ArrayIndexOutOfBoundsException,经过google一番搜索,发现问题在于marshaller的marshal方法不是线程安全的,而JAXBContext.newInstance()是线程安全的。为了解决这一问题,需要将代码进行改造
为了尽量少的重复创建marshaller对象(创建marshaller对象的操作官方认为是比较耗CPU的)这里使用对象池的概念,开发包使用commons-pool,这里用到了KeyedObjectPool
static KeyedObjectPool marPool = new GenericKeyedObjectPool(new JaxbMarshallerFactory()); static KeyedObjectPool unmarPool = new GenericKeyedObjectPool(new JaxbUnmarshallerFactory()); class JaxbUnmarshallerFactory extends JaxbMarshallerFactory{ @Override public Object makeObject(Object key) throws Exception { Class<?> clazz = (Class<?>)key; if(contextMap.containsKey(key)){ JAXBContext context = JAXBContext.newInstance(clazz); contextMap.put(clazz, context); } return contextMap.get(clazz).createUnmarshaller(); } } class JaxbMarshallerFactory implements KeyedPoolableObjectFactory{ protected Map<Class<?>,JAXBContext> contextMap = new HashMap<Class<?>,JAXBContext>(); @Override public Object makeObject(Object key) throws Exception { Class<?> clazz = (Class<?>)key; if(!contextMap.containsKey(clazz)){ JAXBContext context = JAXBContext.newInstance(clazz); contextMap.put(clazz, context); } return contextMap.get(clazz).createMarshaller(); } @Override public void destroyObject(Object key, Object obj) throws Exception { contextMap.remove(key); } @Override public boolean validateObject(Object key, Object obj) { return true; } @Override public void activateObject(Object key, Object obj) throws Exception { // System.out.println("user "+Thread.currentThread()+" borrow "+obj.hashCode()); } @Override public void passivateObject(Object key, Object obj) throws Exception { // System.out.println("user "+Thread.currentThread()+" return "+obj.hashCode()); } }这里定义了两个对象池工厂,分别保存marshaller和unmarshaller,感觉应该可以合并到一个工厂中,后面的实践中再加以改进。
在使用时应该注意borrowObject并使用完成后一定要记得returnObject,这样才能达到对象池的效果
public static void toOutputStream(Object o,OutputStream os) throws JAXBException{ Marshaller mar; try { // 从线程池中借出 mar = (Marshaller)marPool.borrowObject(o.getClass()); // 转换对象到XML mar.marshal(o, os); // 归还到对象池 marPool.returnObject(o.getClass(), mar); } catch (Exception e) { logger.error(e); } }
相关文章推荐
- EF(Entity Framework)发生错误”正在创建模型,此时不可使用上下文“的解决办法。 正在创建模型,此时不可使用上下文。如果在 OnModelCreating 方法内使用上下文或如果多个线程同时访问同一上下文实例,可能引发此异常。请注意不保证 DbContext 的实例成员和相关类是线程安全的。 临时解决了这个问题,在Context的构造函数中,禁用了自动初始化:
- Scala使用SimpleDateFormat出现线程安全问题的解决办法
- 在JAVA开发中的中文处理问题及解决办法
- 目录横穿“(Ttaversal)”问题的解决办法
- Tomcat5.x中include页面显示问题解决办法
- J2ME网络连接中显示问题的解决办法
- Javamail中的常见中文乱码问题与解决办法(综合)
- 关于RedHat Linux 9.0下Kylix 3会出现的四个问题的完满解决办法!
- 出现ORA-12560问题的可能性以及相应的解决办法
- struts下的乱码问题的解决办法
- iReport 加 jasper 问题及解决办法
- “Visual Studio .NET 已检测到指定的 Web 服务器运行的不是 ASP.NET 1.1 版...”问题的解决办法
- Java中文识别问题完全解决办法[一]
- PB中关于动态工资项目问题的解决办法
- mysql4.1以上版本连接时出现Client does not support authentication protocol问题解决办法
- 解决wap中文问题的最好办法
- Java中文识别问题完全解决办法[二]
- 解决JBX常见问题最权威的办法(来自borland)
- word和ie在多线程中的操作的问题解决办法
- does not support authentication protocol问题解决办法