高性能的序列化与反序列化:kryo的简单使用
前言: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进行一个简单的封装设计,从而可以多线程安全的使用序列化和反序列化
序列化和反序列化接口设计
- /**
- * 序列化工具(程序调用该接口来实现obj<->byte[]之间的序列化/反序列化)
- * @author eguid
- *
- */
- public interface Serializer{
- /**
- * 序列化
- * @param t
- * @param bytes
- */
- public void serialize(Object t,byte[] bytes);
- /**
- * 序列化
- * @param obj
- * @param bytes
- * @param offset
- * @param count
- */
- public void serialize(Object obj, byte[] bytes, int offset, int count);
- /**
- * 反序列化
- * @param bytes -字节数组
- * @return T<T>
- */
- public <T>T deserialize(byte[] bytes);
- /**
- * 反序列化
- * @param bytes
- * @param offset
- * @param count
- * @return
- */
- public <T>T deserialize(byte[] bytes, int offset, int count);
- }
使用kryo实现上面的接口
- /**
- * 基于kyro的序列化/反序列化工具
- *
- * @author eguid
- *
- */
- public class kryoSerializer implements Serializer {
- // 由于kryo不是线程安全的,所以每个线程都使用独立的kryo
- final ThreadLocal<Kryo> kryoLocal = new ThreadLocal<Kryo>() {
- @Override
- protected Kryo initialValue() {
- Kryo kryo = new Kryo();
- kryo.register(ct, new BeanSerializer<>(kryo, ct));
- return kryo;
- }
- };
- final ThreadLocal<Output> outputLocal = new ThreadLocal<Output>();
- final ThreadLocal<Input> inputLocal = new ThreadLocal<Input>();
- private Class<?> ct = null;
- public kryoSerializer(Class<?> ct) {
- this.ct = ct;
- }
- public Class<?> getCt() {
- return ct;
- }
- public void setCt(Class<?> ct) {
- this.ct = ct;
- }
- @Override
- public void serialize(Object obj, byte[] bytes) {
- Kryo kryo = getKryo();
- Output output = getOutput(bytes);
- kryo.writeObjectOrNull(output, obj, obj.getClass());
- output.flush();
- }
- @Override
- public void serialize(Object obj, byte[] bytes, int offset, int count) {
- Kryo kryo = getKryo();
- Output output = getOutput(bytes, offset, count);
- kryo.writeObjectOrNull(output, obj, obj.getClass());
- output.flush();
- }
- /**
- * 获取kryo
- *
- * @param t
- * @return
- */
- private Kryo getKryo() {
- return kryoLocal.get();
- }
- /**
- * 获取Output并设置初始数组
- *
- * @param bytes
- * @return
- */
- private Output getOutput(byte[] bytes) {
- Output output = null;
- if ((output = outputLocal.get()) == null) {
- output = new Output();
- outputLocal.set(output);
- }
- if (bytes != null) {
- output.setBuffer(bytes);
- }
- return output;
- }
- /**
- * 获取Output
- *
- * @param bytes
- * @return
- */
- private Output getOutput(byte[] bytes, int offset, int count) {
- Output output = null;
- if ((output = outputLocal.get()) == null) {
- output = new Output();
- outputLocal.set(output);
- }
- if (bytes != null) {
- output.writeBytes(bytes, offset, count);
- }
- return output;
- }
- /**
- * 获取Input
- *
- * @param bytes
- * @param offset
- * @param count
- * @return
- */
- private Input getInput(byte[] bytes, int offset, int count) {
- Input input = null;
- if ((input = inputLocal.get()) == null) {
- input = new Input();
- inputLocal.set(input);
- }
- if (bytes != null) {
- input.setBuffer(bytes, offset, count);
- }
- return input;
- }
- @SuppressWarnings("unchecked")
- @Override
- public <T> T deserialize(byte[] bytes, int offset, int count) {
- Kryo kryo = getKryo();
- Input input = getInput(bytes, offset, count);
- return (T) kryo.readObjectOrNull(input, ct);
- }
- @Override
- public <T> T deserialize(byte[] bytes) {
- return deserialize(bytes, 0, bytes.length);
- }
测试一下kryo的序列化和反序列化
为什么使用纳秒,而不用毫秒?与java原生的序列化反序列化要耗时几毫秒不同,kryo序列化和反序列化太快了,单个对象的序列化反序列化速度都在0.0x毫秒左右(如果电脑性能更好的话,会更快)
- Serializer ser = new kryoSerializer(Msg.class);
- for (int i = 0; i < 10; i++) {
- Msg msg = new Msg();
- msg.setVersion_flag(new byte[] { 1, 2, 3 });
- msg.setCrc_code((short) 1);
- msg.setMsg_body(new byte[] { 123, 123, 123, 43, 42, 1, 12, 45, 57, 98 });
- byte[] bytes = new byte[300];
- long start = System.nanoTime();
- ser.serialize(msg, bytes);
- System.err.println("序列化耗时:" + (System.nanoTime() - start));
- System.out.println(msg);
- System.out.println(Arrays.toString(bytes));
- Msg newmsg = null;
- start = System.nanoTime();
- newmsg = ser.deserialize(bytes);
- System.err.println("反序列化耗时:" + (System.nanoTime() - start));
- System.out.println(newmsg);
- }
----end----
高性能的序列化与反序列化:kryo的简单使用的更多相关文章
- 利用php的序列化和反序列化来做简单的数据本地存储
利用php的序列化和反序列化来做简单的数据本地存储 如下程序可以做为一个工具类 /** * 利用php的序列化和反序列化来做简单的数据本地存储 */ class objectdb { private ...
- XmlSerializer 对象的Xml序列化和反序列化
http://www.cnblogs.com/yukaizhao/archive/2011/07/22/xml-serialization.html 这篇随笔对应的.Net命名空间是System.Xm ...
- XmlSerializer 对象的Xml序列化和反序列化,XMLROOT别名设置
这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中 ...
- Windows phone 之XML序列化与反序列化
为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...
- C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化
这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中的对 ...
- XML的序列化和反序列化 详细介绍
为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...
- C# Note4:XML序列化和反序列化(含加密解密等)
前言 在项目中,我们经常用到各种配置文件,比如xml文件.binary文件等等,这里主要根据实践经验介绍下xml文件的序列化和反序列化(毕竟最常用). 实践背景:我要做一个用户管理功能,用户账号信息存 ...
- JAVA中序列化和反序列化中的静态成员问题
关于这个标题的内容是面试笔试中比较常见的考题,大家跟随我的博客一起来学习下这个过程. ? ? JAVA中的序列化和反序列化主要用于: (1)将对象或者异常等写入文件,通过文件交互传输信息: (2)将对 ...
- C#序列化与反序列化方式简单总结
序列化和反序列化 相关类: System.SerializableAttribute特性(或称为属性), System.Runtime.Serialization.ISerializable(自定义序 ...
随机推荐
- java从apk文件获取包名、版本号、icon
依赖:仅依赖aapt.exe 支持:仅限windows 功能:用纯java获取apk文集里的包名,版本号,图标文件[可获取到流直接保存到文件系统] 原理:比较上一篇文章里通过反编译然后解析Androi ...
- virtualbox 4.3.10 ubuntu 12.04 mount share folder bug
virtualbox 4.3.10 不能mount共享文件夹,这是一个bug,参考如下链接 https://www.virtualbox.org/ticket/12879 执行以下命令即可:sudo ...
- python scrapy爬虫框架
http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html scrapy 提取html的标签内容 from scrapy.selec ...
- 扫盲-wpf依赖属性
一.什么是依赖属性 依赖属性就是一种自己可以没有值,并且可以通过绑定从其他数据源获取值.依赖属性可支持WPF中的样式设置.数据绑定.继承.动画及默认值. 将所有的属性都设置为依赖属性并不总是正确的解决 ...
- 剑指Offer:链表中环的入口节点【23】
剑指Offer:链表中环的入口节点[23] 题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 题目分析 第一步确定链表中是否包含环,怎么确定呢?我们定义两个指针橙和 ...
- Java多线程系列 基础篇03 线程的优先级和守护线程
1. 线程优先级 现代操作系统中基本上使用时间分片的方式调度线程,通过设置线程优先级,使优先级高的线程获得时间片的次数多于优先级低的线程. 在java 线程中,通过一个整形变量prority来控制优先 ...
- nodejs中的子进程,深入解析child_process模块和cluster模块
Node.js的进程管理 node遵循的是单线程单进程的模式,node的单线程是指js的引擎只有一个实例,且在nodejs的主线程中执行,同时node以事件驱动的方式处理IO等异步操作.node的 ...
- python源码安装的包的卸载
python setup.py install安装的包如何卸载 在使用源码安装的过程中,记录安装文件细节,如: python setup.py install --record log 这时所有的安装 ...
- 20145239杜文超 实验五 Java网络编程
20145239 实验五 Java网络编程 实验内容 组队,一人服务器,一人客户端. 下载加解密代码,先编译运行代码,一人加密一人解密,适当修改代码. 然后集成代码,一人加密后通过TCP发送,加密使用 ...
- 《C prime plus (第五版)》 ---第12章 存储类.链接和内存管理
12-1:存储类: 1.作用域: 代码块作用域,函数原型作用域和文件作用域. 2.链接:分为外部链接,内部链接和空链接.代码块作用域和函数原型作用域都是空连接,意味着是私有的.而文件作用域的变量可能是 ...