编解码技术- 序列化工具Serializable

1、编解码名词含义:将java对象编码为字节数组或者bytebuffer对象,当远程服务读取到byterbuffer对象或者字节数组是,需要将其编解码为发送是的java对象。

2、我用过的序列化方式以下三种:1)对象实现Serializable接口  2)使用google的json或者阿里巴巴的FastJSon   3)使用google的protobuf   4)Facebook的Thrift  主要用于静态数据交换,已知的数据结构,负责搭建大型数据交换接存储的工具  5)Jboss的Marshalling 是一个java对象的序列化api包

本次主要查看第一种serializable 序列化后的编码性能,码流大小,api工具是否方便

1)pojo类

public class UserInfo implements Serializable {
    private  static final long serialVersionUid=1L;
    private String userName;
    private  int userID;

    public UserInfo buildUserName(String username) {
        this.userName = username;
        return this;
    }

    public UserInfo buildUserID(int userID) {
        this.userID = userID;
        return this;
    }

    public final String getUserName() {
        return userName;
    }

    public final  void setUserName(String userName) {
        this.userName = userName;
    }

    public final int getUserID() {
        return userID;
    }

    public final  void setUserID(int userID) {
        this.userID = userID;
    }
    public byte[] codeC(){
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        byte[] bytes = this.userName.getBytes();
        buffer.putInt(bytes.length);
        buffer.put(bytes);
        buffer.putInt(this.userID);
        buffer.flip();
        bytes=null;
        byte[] result = new byte[buffer.remaining()];
        buffer.get(result);
        return result;
    }

usrinfo对象是一个普通pojo类,它实现了serializable接口,,通过jdk默认的序列化机制进行序列化和反序列化。

codec方法使用的是bytebuffer通用的二进制编码技术对userinfo对象进行编码,编码结果仍然是byte数组,

2)测试类

public class TestUserInfo {
    public static void main(String[] args) throws IOException {
        UserInfo userInfo = new UserInfo();
        userInfo.buildUserID(100).buildUserName("welcome to netty");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream os = new ObjectOutputStream(bos);
        os.writeObject(userInfo);
        os.flush();
        os.close();
        byte[] bytes = bos.toByteArray();
        System.out.println("the jdk serializable length is:"+bytes.length);
        bos.close();
        System.out.println("=====================================");
        System.out.println("the byte array serializable length:"+userInfo.codeC().length);
    }
}

3)运行结果


从上可以看出,二进制明细优于jdk序列化。因为编解码后的字节数组越大,存储的时候约占空间,硬件成本就越高,网络传送就越高,

4)编码100万次,新增一个重载方法

/**
 * 修改后的
 * @return
 */
public byte[] codeC(ByteBuffer buffer){
     buffer.clear();
    byte[] bytes = this.userName.getBytes();
    buffer.putInt(bytes.length);
    buffer.put(bytes);
    buffer.putInt(this.userID);
    buffer.flip();
    bytes=null;
    byte[] result = new byte[buffer.remaining()];
    buffer.get(result);
    return result;
}

public class PerformTestUserInfo {
    public static void main(String[] args) throws IOException {
        UserInfo userInfo = new UserInfo();
        userInfo.buildUserID(100).buildUserName("weclome to netty");
        int loop=1000000;
        ByteArrayOutputStream bos=null;
        ObjectOutputStream os=null;
        long startTime = System.currentTimeMillis();
        for(int i=0;i<loop;i++){
            bos=new ByteArrayOutputStream();
            os=new ObjectOutputStream(bos);
            os.writeObject(userInfo);
            os.flush();
            os.close();
            byte[] bytes = bos.toByteArray();
            bos.close();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("the jdk serializable cost time is:"+(endTime-startTime)+"ms");

        System.out.println("=====================================");


        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
         startTime = System.currentTimeMillis();
         for(int i=0;i<loop;i++){
             byte[] bytes = userInfo.codeC(byteBuffer);
         }
        endTime = System.currentTimeMillis();
        System.out.println("the byte array serializable cost time is:"+(endTime-startTime)+"ms");
    }
}

,统计下测试时间:

以上结果证明:无论序列化后的码流大小还是序列化的性能,jdk默认的序列化都很差,

猜你喜欢

转载自blog.csdn.net/skycanf/article/details/80282773
今日推荐