前言:kryo是个高效的java序列化/反序列化库,目前Twitter、yahoo、Apache、strom等等在使用该技术,好比Apache的spark、hive等大数据领域用的较多。java
为何使用kryo而不是其余?
由于性能足够好。比kyro更高效的序列化库就只有google的protobuf了(并且二者性能很接近),protobuf有个缺点就是要传输的每个类的结构都要生成对应的proto文件(也能够都放在同一个proto文件中,若是考虑到扩展性的话,不建议放在一个proto文件中),若是某个类发生修改,还得从新生成该类对应的proto文件;另外考虑到项目中用的所有是java技术栈,不存在不一样编程语言间的兼容性问题,所以最终采用了kryo做为序列化库。redis
使用场景:(数据交换或数据持久化)好比使用kryo把对象序列化成字节数组发送给消息队列或者放到redis等nosql中等等应用场景。sql
注意:因为kryo不是线程安全的,针对多线程状况下的使用,要对kryo进行一个简单的封装设计,从而能够多线程安全的使用序列化和反序列化编程
序列化和反序列化接口设计
-
-
-
-
-
-
public interface Serializer{
-
-
-
-
-
-
-
public void serialize(Object t,byte[] bytes);
-
-
-
-
-
-
-
-
-
public void serialize(Object obj, byte[] bytes, int offset, int count);
-
-
-
-
-
-
-
public <T>T deserialize(byte[] bytes);
-
-
-
-
-
-
-
-
-
-
public <T>T deserialize(byte[] bytes, int offset, int count);
-
-
使用kryo实现上面的接口
-
-
-
-
-
-
-
public class kryoSerializer implements Serializer {
-
-
-
final ThreadLocal<Kryo> kryoLocal = new ThreadLocal<Kryo>() {
-
-
protected Kryo initialValue() {
-
-
kryo.register(ct,
new BeanSerializer<>(kryo, ct));
-
-
-
-
final ThreadLocal<Output> outputLocal = new ThreadLocal<Output>();
-
final ThreadLocal<Input> inputLocal = new ThreadLocal<Input>();
-
private Class<?> ct = null;
-
-
public kryoSerializer(Class<?> ct) {
-
-
-
-
public Class<?> getCt() {
-
-
-
-
public void setCt(Class<?> ct) {
-
-
-
-
-
public void serialize(Object obj, byte[] bytes) {
-
-
Output output = getOutput(bytes);
-
kryo.writeObjectOrNull(output, obj, obj.getClass());
-
-
-
-
-
public void serialize(Object obj, byte[] bytes, int offset, int count) {
-
-
Output output = getOutput(bytes, offset, count);
-
kryo.writeObjectOrNull(output, obj, obj.getClass());
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
private Output getOutput(byte[] bytes) {
-
-
if ((output = outputLocal.get()) == null) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
private Output getOutput(byte[] bytes, int offset, int count) {
-
-
if ((output = outputLocal.get()) == null) {
-
-
-
-
-
output.writeBytes(bytes, offset, count);
-
-
-
-
-
-
-
-
-
-
-
-
-
private Input getInput(byte[] bytes, int offset, int count) {
-
-
if ((input = inputLocal.get()) == null) {
-
-
-
-
-
input.setBuffer(bytes, offset, count);
-
-
-
-
-
@SuppressWarnings("unchecked")
-
-
public <T> T deserialize(byte[] bytes, int offset, int count) {
-
-
Input input = getInput(bytes, offset, count);
-
return (T) kryo.readObjectOrNull(input, ct);
-
-
-
-
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.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(Arrays.toString(bytes));
-
-
-
start = System.nanoTime();
-
newmsg = ser.deserialize(bytes);
-
System.err.println(
"反序列化耗时:" + (System.nanoTime() - start));
-
System.out.println(newmsg);
-
----end----安全