protostuff序列化集合的问题(反序列化时的java.util.ConcurrentModificationException)

来源:互联网 发布:jsp项目开发案例 源码 编辑:程序博客网 时间:2024/05/22 17:17

之前写过一篇关于JDK原始支持的Serializable接口序列化与Google的Protostuff序列化两种技术的比较(http://blog.csdn.net/canot/article/details/53750443)。Protostuff序列化的性能,空间利用率远高于Serializable接口。基于这些原因,最近在做
MyBatis开发的过程中使用二级缓存的时候就使用了Protostuff与Redis数据库来做序列化。
Protostuff完成一个序列化与反序列化的代码比较简单:
Maven依赖

      <dependency>            <groupId>io.protostuff</groupId>            <artifactId>protostuff-core</artifactId>            <version>1.4.4</version>        </dependency>        <dependency>            <groupId>io.protostuff</groupId>            <artifactId>protostuff-runtime</artifactId>            <version>1.4.4</version>        </dependency>

核心代码

//制定要序列化的对象private static RuntimeSchema<Person> schema = RuntimeSchema.createFrom(Person.class);/***序列化*/Person crab = new Person();  crab.setName("kaka");  //参数三缓冲器byte[] bytes = ProtostuffIOUtil.toByteArray(crab,schema,LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));/** *反序列化 */// 空对象Person newCrab = schema.newMessage();ProtostuffIOUtil.mergeFrom(bytes,newCrab,schema);System.out.println("Hi, My name is " + newCrab.getName());

上述代码是没有任何问题的。然后当使用在MyBatis二级缓存上的时候,情况有一点点不一样。
众所周知,二级缓存只使用在select语句上,而select语句查询出来的数据是个List,并且是个ArrayList。
那么想当然的将Protostuff的schema制定为ArrayList

    private static RuntimeSchema<ArrayList> schema = RuntimeSchema.createFrom(ArrayList.class);

如果指定为List接口编译都通过不了,schema无法指定为接口或抽象类
然后的操作无非就是序列化,反序列化,在我打印日志查看的时候,序列化过程是没有如何问题的。但当我开始执行反序列化操作,要将byte数组还原为ArrayList集合的时候,编译器抛出了一个异常

java.util.ConcurrentModificationException

对于Java集合比较熟悉的朋友应该知道这是个并发操作异常,出现的情况是在编辑集合的过程中对集合进行了增删操作。当时我的解决办法是定义一个类,一个专门做为Protostuff schema的类,它只包含一个字段ArrayList

class CacheEntry{    private List<Seckill> seckills;    public CacheEntry(List<Seckill> seckills){        this.seckills=seckills;    }    public List<Seckill> getSeckills() {        return seckills;    }    public void setSeckills(List<Seckill> seckills) {        this.seckills = seckills;    }}

然后将select出来的数据放入这个类的实体中,对这个实体做序列化,反序列化操作。

    private static RuntimeSchema<CacheEntry> schema = RuntimeSchema.createFrom(CacheEntry.class);

完美运行。

阅读全文
0 0
原创粉丝点击