Kryo 高性能序列化和反序列化
一、pom.xml
<dependency><groupId>com.esotericsoftware</groupId><artifactId>kryo</artifactId><version>4.0.0</version>
</dependency>
二、封装工具类
package com.cxs.web.system.kryo;import com.cxs.common.util.ArrayUtil;
import com.cxs.common.util.Collections;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.pool.KryoCallback;
import com.esotericsoftware.kryo.pool.KryoFactory;
import com.esotericsoftware.kryo.pool.KryoPool;
import org.objenesis.strategy.StdInstantiatorStrategy;
import org.springframework.util.StopWatch;import java.io.*;
import java.util.*;/*** KryoUtils序列化和反序列化操作官方文档:中文:https://blog.csdn.net/fanjunjaden/article/details/72823866英文:https://github.com/EsotericSoftware/kryo*/
public class KryoUtils {/* Kryo有三组读写对象的方法* 1.如果不知道对象的具体类,且对象可以为null: kryo.writeClassAndObject(output, object); Object object = kryo.readClassAndObject(input);* 2.如果类已知且对象可以为null: kryo.writeObjectOrNull(output, someObject); SomeClass someObject = kryo.readObjectOrNull(input, SomeClass.class);* 3.如果类已知且对象不能为null: kryo.writeObject(output, someObject); SomeClass someObject = kryo.readObject(input, SomeClass.class);*//*** (池化Kryo实例)使用ThreadLocal*/private static final ThreadLocal<Kryo> KRYOS = new ThreadLocal<Kryo>() {@Overrideprotected Kryo initialValue() {Kryo kryo = new Kryo();/*** 不要轻易改变这里的配置,更改之后,序列化的格式就会发生变化,* 上线的同时就必须清除 Redis 里的所有缓存,* 否则那些缓存再回来反序列化的时候,就会报错*///支持对象循环引用(否则会栈溢出)kryo.setReferences(true); //默认值就是 true,添加此行的目的是为了提醒维护者,不要改变这个配置//不强制要求注册类(注册行为无法保证多个 JVM 内同一个类的注册编号相同;而且业务系统中大量的 Class 也难以一一注册)kryo.setRegistrationRequired(false); //默认值就是 false,添加此行的目的是为了提醒维护者,不要改变这个配置//Fix the NPE bug when deserializing Collections.((Kryo.DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy()).setFallbackInstantiatorStrategy(new StdInstantiatorStrategy());return kryo;}};/*** (池化Kryo实例)使用KryoPool*//*private static KryoFactory factory1 = new KryoFactory() {@Overridepublic Kryo create () {return new Kryo();}};private static KryoFactory factory2 = () -> { return new Kryo(); };private static KryoFactory factory3 = () -> new Kryo();*/private static KryoFactory factory = Kryo::new;private static KryoPool pool = new KryoPool.Builder(factory).softReferences().build();/*** 使用ThreadLocal创建Kryo* 把java对象序列化成byte[];* @param obj java对象* @return*/public static <T> byte[] serializeObject(T obj) {ByteArrayOutputStream os=null;Output output=null;if(null != obj){Kryo kryo = KRYOS.get();try {os = new ByteArrayOutputStream();output = new Output(os);kryo.writeObject(output, obj);close(output);return os.toByteArray();} catch (Exception e) {e.printStackTrace();}finally {close(os);}}return null;}/*** 使用ThreadLocal创建Kryo* 把byte[]反序列化成指定的java对象* @param bytes* @param t 指定的java对象* @param <T>* @return 指定的java对象*/public static <T> T unSerializeObject(byte[] bytes,Class<T> t) {ByteArrayInputStream is=null;Input input=null;if(null != bytes && bytes.length>0 && null!=t){try {Kryo kryo = KRYOS.get();is = new ByteArrayInputStream(bytes);input = new Input(is);return kryo.readObject(input,t);} catch (Exception e) {e.printStackTrace();}finally {close(is);close(input);}}return null;}/*** 使用ThreadLocal创建Kryo* 把List序列化成byte[];* @param list java对象* @return*/public static <T> byte[] serializeList(List<T> list ) {ByteArrayOutputStream os=null;Output output=null;byte[] bytes = null;if(null != list && list.size()>0){Kryo kryo = KRYOS.get();try {os = new ByteArrayOutputStream();output = new Output(os);kryo.writeObject(output,list);close(output);bytes = os.toByteArray();return bytes;} catch (Exception e) {e.printStackTrace();}finally {close(os);}}return null;}/*** 使用ThreadLocal创建Kryo* 把byte[]反序列化成指定的List<T>* @param bytes byte数组* @param <T>* @return 指定java对象的List*/public static <T> List<T> unSerializeList(byte[] bytes) {ByteArrayInputStream is=null;Input input=null;if(null !=bytes && bytes.length>0){try {Kryo kryo = KRYOS.get();is = new ByteArrayInputStream(bytes);input = new Input(is);List<T> list = kryo.readObject(input,ArrayList.class);return list;} catch (Exception e) {e.printStackTrace();}finally {close(is);close(input);}}return null;}/*** 使用ThreadLocal创建Kryo* 把java对象转序列化存储在文件中;* @param obj java对象* @return*/public static <T> boolean serializeFile(T obj,String path) {if(null != obj){Output output=null;try {Kryo kryo = KRYOS.get();output = new Output(new FileOutputStream(path));kryo.writeObject(output, obj);return true;} catch (Exception e) {e.printStackTrace();}finally {close(output);}}return false;}/*** 使用ThreadLocal创建Kryo* 把序列化的文件反序列化成指定的java对象* @param path 文件路径* @param t 指定的java对象* @param <T>* @return 指定的java对象*/public static <T> T unSerializeFile(String path,Class<T> t) {if(null != path && null !=t ){Input input=null;try {Kryo kryo = KRYOS.get();input = new Input(new FileInputStream(path));return kryo.readObject(input,t);} catch (Exception e) {e.printStackTrace();}finally {close(input);}}return null;}/*** 使用KryoPool SoftReferences创建Kryo* 把java对象序列化成byte[] ;* @param obj java对象* @return*/public static <T> byte[] serializePoolSoftReferences (T obj) {if(null!=obj){Kryo kryo =pool.borrow();ByteArrayOutputStream os=null;Output output=null;try {os = new ByteArrayOutputStream();output = new Output(os);kryo.writeObject(output, obj);close(output);byte [] bytes = os.toByteArray();return bytes;} catch (Exception e) {e.printStackTrace();}finally {pool.release(kryo);close(os);}}return null;}/*** 使用KryoPool SoftReferences创建Kryo* 把byte[]反序列化成指定的java对象* @param bytes* @return*/public static <T> T unSerializePoolSoftReferences(byte[] bytes,Class<T> t) {if(null !=bytes && bytes.length>0 && null!=t){Kryo kryo =pool.borrow();ByteArrayInputStream is=null;Output output=null;try {is = new ByteArrayInputStream(bytes);Input input= new Input(is);return kryo.readObject(input, t);} catch (Exception e) {e.printStackTrace();}finally {pool.release(kryo);close(is);close(output);}}return null;}/*** 使用KryoPool SoftReferences创建Kryo* 把java对象序列化成byte[] ;* @param obj java对象* @return*/public static <T> byte[] serializePoolCallback (final T obj) {if(null != obj){try {return pool.run(new KryoCallback<byte[]>() {@Overridepublic byte[] execute(Kryo kryo) {ByteArrayOutputStream os = new ByteArrayOutputStream();Output output = new Output(os);kryo.writeObject(output,obj);output.close();try {os.close();} catch (IOException e) {e.printStackTrace();}return os.toByteArray();}});} catch (Exception e) {e.printStackTrace();}}return null;}/*** 使用KryoPool SoftReferences创建Kryo* 把byte[]反序列化成指定的java对象* @param bytes* @return*/public static <T> T unSerializePoolCallback(final byte[] bytes, final Class<T> t) {if(null != bytes && bytes.length>0 && null != t){try {return pool.run(new KryoCallback<T>() {@Overridepublic T execute(Kryo kryo) {ByteArrayInputStream is = new ByteArrayInputStream(bytes);Input input = new Input(is);T result =kryo.readObject(input,t);input.close();try {is.close();} catch (IOException e) {e.printStackTrace();}return result;}});} catch (Exception e) {e.printStackTrace();}}return null;}/*** 关闭io流对象** @param closeable*/public static void close(Closeable closeable) {if (closeable != null) {try {closeable.close();} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) throws FileNotFoundException {Clazz clazz1 = new Clazz("3年级1班", "java", 1);Clazz clazz2 = new Clazz("3年级2班", ".net", 2);Clazz clazz3 = new Clazz("3年级3班", "vue", 3);Student student1 = new Student("张三", 18, new Date(), '1', true, clazz1);Student student2 = new Student("李四", 28, new Date(System.currentTimeMillis()-1000*60*60*24), '1', true, clazz1);Student student3 = new Student("王五", 38, new Date(System.currentTimeMillis()-1000*60*60*24*2), '2', false, clazz2);Student student4 = new Student("赵六", 48, new Date(System.currentTimeMillis()-1000*60*60*24*3), '1', true, clazz3);Student student5 = new Student("刘七", 58, new Date(System.currentTimeMillis()-1000*60*60*24*4), '2', false, clazz1);List<Student> studentList = Arrays.asList(student1, student2, student3, student4, student5);System.out.println("===kryo序列化===");StopWatch stopWatch = new StopWatch("kryo序列化/反序列化");stopWatch.start("kryo序列化/反序列化");for(int i = 0; i < 1000000; i++) {unSerializeObject(serializeObject(studentList), ArrayList.class);}stopWatch.stop();System.out.println(stopWatch.getId() + "-totalTimeMillis:" + stopWatch.getTotalTimeMillis());System.out.println("===jdk序列化===");stopWatch = new StopWatch("jdk序列化/反序列化");stopWatch.start("jdk序列化/反序列化");for(int i = 0; i < 1000000; i++) {Collections.deepCopy(studentList);}stopWatch.stop();System.out.println(stopWatch.getId() + "-totalTimeMillis:" + stopWatch.getTotalTimeMillis());}
}
三、与jdk序列化/反序列化的性能测试
1. 循环1万次测试
测试结果:kryo高于jdk 3倍效率
2. 循环10万次测试
测试结果:kryo高于jdk 4倍效率
3. 循环100万次测试
测试结果:kryo高于jdk 5倍效率
四、总结
序列化/反序列化 次数越多,效果越明显!
Kryo 高性能序列化和反序列化相关推荐
- 高性能的序列化与反序列化:kryo的简单使用
前言:kryo是个高效的java序列化/反序列化库,目前Twitter.yahoo.Apache.strom等等在使用该技术,比如Apache的spark.hive等大数据领域用的较多. 为什么使用k ...
- 【RPC】序列化与反序列化
文章目录 1. 基本概念? 2. 文本格式的序列化方案 2.1 XML格式 2.2 JSON格式 3. 二进制格式的序列化方法 4. 序列化框架选型 1. 基本概念? 序列化和反序列化是一种数据转化的 ...
- Java序列化与反序列化的深度思考
目录 1.序列化与反序列化的作用 2.序列化协议 2.1 JDK序列化协议 2.1.1 Externalizable与Serializable的异同 2.2 Google ProtocolBuf 协 ...
- dubbo源码分析25 -- 序列化与反序列化
序列化:把对象转换为字节序列的过程称为对象的序列化. 反序列化:把字节序列恢复为对象的过程称为对象的反序列化. Dubbo是 Alibaba 开源的分布式服务框架远程调用框架,现在已捐赠给 apach ...
- 序列化和反序列化(转)
转载:http://kb.cnblogs.com/page/515982/ 摘要 序列化和反序列化几乎是工程师们每天都要面对的事情,但是要精确掌握这两个概念并不容易:一方面,它们往往作为框架的一部分出 ...
- 使用Kryo的序列化方式提升Netty性能
2019独角兽企业重金招聘Python工程师标准>>> 为什么选择Kryo? 首先,Kryo的序列化方式,在性能方面是比较好的,和Protobuf差不多,比Java原生的序列化方式快 ...
- Redkale 技术详解 03 -- Convert高性能序列化
2019独角兽企业重金招聘Python工程师标准>>> Convert是个重复造轮子的组件,却是个飞速的轮子.Redkale之所以重复造轮子主要追求性能和需要与网络数据的序列化很好的 ...
- 序列化和反序列化--转
http://www.infoq.com/cn/articles/serialization-and-deserialization 简介 文章作者服务于美团推荐与个性化组,该组致力于为美团用户提供每 ...
- java高性能序列化_Java最佳实践–高性能序列化
java高性能序列化 在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论并演示如何将对象序列化用于高性能应用程序. 所有讨论的主题均基于用例,这些用例源于电信行业关键任务超 ...
- Java最佳实践–高性能序列化
在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论并演示如何将对象序列化用于高性能应用程序. 所有讨论的主题均基于用例,这些用例来自于电信行业的关键任务超高性能生产系统的开 ...
最新文章
- 这几个 Python 的小技巧,你会么?
- OKR让伟大的企业愿景成为可能
- java automapper 使用_19.AutoMapper 之开放式泛型(Open Generics)
- 【AllJoyn专题】基于AllJoyn和Yeelink的传感器数据上传与指令下行的研究
- java类是如何加载的?不知道classLoader和双亲委派,不是一个合格的程序员
- 更改centos 7 的默认启动为命令界面
- 第五周 Leetcode 99. Recover Binary Search Tree (HARD)
- mysql+join的原理,Mysql连接join查询原理知识点
- ~~朴素dijkstra算法 (搜索与图论)(附模板题AcWing 849. Dijkstra求最短路 I)
- 生成和解析二维码(zxing)
- 使用码云或GitHub搭建简单的个人网站
- 关于Session、Cookie、Token你知道多少?
- PUBG 绝地逃亡 吃鸡压枪宏 彩虹六号压枪宏 Autohotkey
- 挖掘机液压控制系统实训QY-JXSX09
- RK3399平台开发系列讲解(内核驱动外设篇)6.8、视频解码芯片GM7150驱动的添加
- 免费申请ssl证书并部署
- WPS Linux版的公式自动编号且右对齐的方法
- win10的系统mysql服务器地址,win10的系统mysql服务器地址
- Blueprint介绍和使用
- Wi-Fi理论基础概述