前言:kryo是个高效的java序列化/反序列化库,目前Twitter、yahoo、Apache、strom等等在使用该技术,比如Apache的spark、hive等大数据领域用的较多。

为什么使用kryo而不是其他?

因为性能足够好。比kyro更高效的序列化库就只有google的protobuf了(而且两者性能很接近),protobuf有个缺点就是要传输的每一个类的结构都要生成对应的proto文件(也可以都放在同一个proto文件中,如果考虑到扩展性的话,不建议放在一个proto文件中),如果某个类发生修改,还得重新生成该类对应的proto文件;另外考虑到项目中用的全部是java技术栈,不存在不同编程语言间的兼容性问题,因此最终采用了kryo作为序列化库。

使用场景:(数据交换或数据持久化)比如使用kryo把对象序列化成字节数组发送给消息队列或者放到redis等nosql中等等应用场景。

注意:由于kryo不是线程安全的,针对多线程情况下的使用,要对kryo进行一个简单的封装设计,从而可以多线程安全的使用序列化和反序列化

序列化和反序列化接口设计

  1. /**
  2. * 序列化工具(程序调用该接口来实现obj<->byte[]之间的序列化/反序列化)
  3. * @author eguid
  4. *
  5. */
  6. public interface Serializer{
  7.  
  8. /**
  9. * 序列化
  10. * @param t
  11. * @param bytes
  12. */
  13. public void serialize(Object t,byte[] bytes);
  14.  
  15. /**
  16. * 序列化
  17. * @param obj
  18. * @param bytes
  19. * @param offset
  20. * @param count
  21. */
  22. public void serialize(Object obj, byte[] bytes, int offset, int count);
  23.  
  24. /**
  25. * 反序列化
  26. * @param bytes -字节数组
  27. * @return T<T>
  28. */
  29. public <T>T deserialize(byte[] bytes);
  30.  
  31.  
  32. /**
  33. * 反序列化
  34. * @param bytes
  35. * @param offset
  36. * @param count
  37. * @return
  38. */
  39. public <T>T deserialize(byte[] bytes, int offset, int count);
  40.  
  41. }

使用kryo实现上面的接口

  1. /**
  2. * 基于kyro的序列化/反序列化工具
  3. *
  4. * @author eguid
  5. *
  6. */
  7. public class kryoSerializer implements Serializer {
  8.  
  9. // 由于kryo不是线程安全的,所以每个线程都使用独立的kryo
  10. final ThreadLocal<Kryo> kryoLocal = new ThreadLocal<Kryo>() {
  11. @Override
  12. protected Kryo initialValue() {
  13. Kryo kryo = new Kryo();
  14. kryo.register(ct, new BeanSerializer<>(kryo, ct));
  15. return kryo;
  16. }
  17. };
  18. final ThreadLocal<Output> outputLocal = new ThreadLocal<Output>();
  19. final ThreadLocal<Input> inputLocal = new ThreadLocal<Input>();
  20. private Class<?> ct = null;
  21.  
  22. public kryoSerializer(Class<?> ct) {
  23. this.ct = ct;
  24. }
  25.  
  26. public Class<?> getCt() {
  27. return ct;
  28. }
  29.  
  30. public void setCt(Class<?> ct) {
  31. this.ct = ct;
  32. }
  33.  
  34. @Override
  35. public void serialize(Object obj, byte[] bytes) {
  36. Kryo kryo = getKryo();
  37. Output output = getOutput(bytes);
  38. kryo.writeObjectOrNull(output, obj, obj.getClass());
  39. output.flush();
  40. }
  41.  
  42. @Override
  43. public void serialize(Object obj, byte[] bytes, int offset, int count) {
  44. Kryo kryo = getKryo();
  45. Output output = getOutput(bytes, offset, count);
  46. kryo.writeObjectOrNull(output, obj, obj.getClass());
  47. output.flush();
  48. }
  49.  
  50. /**
  51. * 获取kryo
  52. *
  53. * @param t
  54. * @return
  55. */
  56. private Kryo getKryo() {
  57. return kryoLocal.get();
  58. }
  59.  
  60. /**
  61. * 获取Output并设置初始数组
  62. *
  63. * @param bytes
  64. * @return
  65. */
  66. private Output getOutput(byte[] bytes) {
  67. Output output = null;
  68. if ((output = outputLocal.get()) == null) {
  69. output = new Output();
  70. outputLocal.set(output);
  71. }
  72. if (bytes != null) {
  73. output.setBuffer(bytes);
  74. }
  75. return output;
  76. }
  77.  
  78. /**
  79. * 获取Output
  80. *
  81. * @param bytes
  82. * @return
  83. */
  84. private Output getOutput(byte[] bytes, int offset, int count) {
  85. Output output = null;
  86. if ((output = outputLocal.get()) == null) {
  87. output = new Output();
  88. outputLocal.set(output);
  89. }
  90. if (bytes != null) {
  91. output.writeBytes(bytes, offset, count);
  92. }
  93. return output;
  94. }
  95.  
  96. /**
  97. * 获取Input
  98. *
  99. * @param bytes
  100. * @param offset
  101. * @param count
  102. * @return
  103. */
  104. private Input getInput(byte[] bytes, int offset, int count) {
  105. Input input = null;
  106. if ((input = inputLocal.get()) == null) {
  107. input = new Input();
  108. inputLocal.set(input);
  109. }
  110. if (bytes != null) {
  111. input.setBuffer(bytes, offset, count);
  112. }
  113. return input;
  114. }
  115.  
  116. @SuppressWarnings("unchecked")
  117. @Override
  118. public <T> T deserialize(byte[] bytes, int offset, int count) {
  119. Kryo kryo = getKryo();
  120. Input input = getInput(bytes, offset, count);
  121. return (T) kryo.readObjectOrNull(input, ct);
  122. }
  123.  
  124. @Override
  125. public <T> T deserialize(byte[] bytes) {
  126. return deserialize(bytes, 0, bytes.length);
  127. }

测试一下kryo的序列化和反序列化

为什么使用纳秒,而不用毫秒?与java原生的序列化反序列化要耗时几毫秒不同,kryo序列化和反序列化太快了,单个对象的序列化反序列化速度都在0.0x毫秒左右(如果电脑性能更好的话,会更快)

  1. Serializer ser = new kryoSerializer(Msg.class);
  2. for (int i = 0; i < 10; i++) {
  3.  
  4. Msg msg = new Msg();
  5.  
  6. msg.setVersion_flag(new byte[] { 1, 2, 3 });
  7. msg.setCrc_code((short) 1);
  8. msg.setMsg_body(new byte[] { 123, 123, 123, 43, 42, 1, 12, 45, 57, 98 });
  9. byte[] bytes = new byte[300];
  10. long start = System.nanoTime();
  11. ser.serialize(msg, bytes);
  12. System.err.println("序列化耗时:" + (System.nanoTime() - start));
  13. System.out.println(msg);
  14. System.out.println(Arrays.toString(bytes));
  15.  
  16. Msg newmsg = null;
  17. start = System.nanoTime();
  18. newmsg = ser.deserialize(bytes);
  19. System.err.println("反序列化耗时:" + (System.nanoTime() - start));
  20. System.out.println(newmsg);
  21. }

----end----

高性能的序列化与反序列化:kryo的简单使用的更多相关文章

  1. 利用php的序列化和反序列化来做简单的数据本地存储

    利用php的序列化和反序列化来做简单的数据本地存储 如下程序可以做为一个工具类 /** * 利用php的序列化和反序列化来做简单的数据本地存储 */ class objectdb { private ...

  2. XmlSerializer 对象的Xml序列化和反序列化

    http://www.cnblogs.com/yukaizhao/archive/2011/07/22/xml-serialization.html 这篇随笔对应的.Net命名空间是System.Xm ...

  3. XmlSerializer 对象的Xml序列化和反序列化,XMLROOT别名设置

    这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间.   为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中 ...

  4. Windows phone 之XML序列化与反序列化

    为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...

  5. C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化

    这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中的对 ...

  6. XML的序列化和反序列化 详细介绍

    为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...

  7. C# Note4:XML序列化和反序列化(含加密解密等)

    前言 在项目中,我们经常用到各种配置文件,比如xml文件.binary文件等等,这里主要根据实践经验介绍下xml文件的序列化和反序列化(毕竟最常用). 实践背景:我要做一个用户管理功能,用户账号信息存 ...

  8. JAVA中序列化和反序列化中的静态成员问题

    关于这个标题的内容是面试笔试中比较常见的考题,大家跟随我的博客一起来学习下这个过程. ? ? JAVA中的序列化和反序列化主要用于: (1)将对象或者异常等写入文件,通过文件交互传输信息: (2)将对 ...

  9. C#序列化与反序列化方式简单总结

    序列化和反序列化 相关类: System.SerializableAttribute特性(或称为属性), System.Runtime.Serialization.ISerializable(自定义序 ...

随机推荐

  1. 最短路 uva12661 Funny Car Racing

    传送门:点击打开链接 题意:给你有向图,每条边呈周期性开放,即开放a时间,再关闭b时间.再开放a时间以此类推 假设时间不足以穿过这条路则不能走.你能够在节点等待时间,问从s走到t所须要的最小时间 细致 ...

  2. 分布式搜索elasticsearch 环境搭建

    1.elasticsearch安装 elasticsearch的安装超级easy,解压即用(要事先安装好java环境). 到官网 http://www.elasticsearch.org下载最新版的 ...

  3. Eclipse工程前面有个红色的感叹号的解决办法

    今天从SVN下载下工程之后,编译完,发现有两个工程有个红色的感叹号,一直没找到什么原因,问百度老师,发现问题的解决办法了. 1.先在控制台上点击Problems 如果控制台没有Problems,点击工 ...

  4. Redis单台的安装部署及集群部署

    Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集(diff ...

  5. Echache整合Spring缓存实例解说

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要介绍了EhCache,并通过整合Spring给出了一个使用实例. 一.EhCac ...

  6. iOS开发 僵尸调试

    本文转载至 http://blog.sina.com.cn/s/blog_a843a8850101dxin.html   引自:http://blog.csdn.net/likendsl/articl ...

  7. Asp.Net中判断是否登录,及是否有权限?

    不需要在每个页面都做判段, 方法一:只需要做以下处理即可 using System; using System.Collections.Generic; using System.Linq; usin ...

  8. mongo数据库中一条记录中某个属性是数组情形时 数据结构的定义

    package entity; import java.util.Date; import com.mongodb.BasicDBList;import com.mongodb.DBObject; p ...

  9. 九度OJ 1173:查找 (排序、查找)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5808 解决:3163 题目描述: 输入数组长度 n  输入数组      a[1...n]  输入查找个数m  输入查找数字b[1...m ...

  10. 九度OJ 1078:二叉树遍历 (二叉树)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3748 解决:2263 题目描述: 二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树 ...