今天在写code时,要调用thrift的TDeserializer.deserialize()方法,发现其提供的接口很不好用。会导致应用代码的多一次copy。
thrift源码如下:
public void deserialize(TBase base, byte[] bytes) throws TException {
base.read(
protocolFactory_.getProtocol(
new TIOStreamTransport(
new ByteArrayInputStream(bytes))));
}
可以看出,这里只可以传如byte[].
在应用程序中, 如果采用buffer复用,就会要导致buffer的不定长,这样的话,要调用此函数就要求一个中间的copy过程,(由于java中并无array的slice,据我所知效率最高的数组copy是System.arrayCopy(),调用native方法),导致浪费空间和时间。
解决方法是, 添加此方法,但需编译thrift.jar
public void deserialize(TBase base, byte[] bytes, int offset, int len) throws TException {
base.read(
protocolFactory_.getProtocol(
new TIOStreamTransport(
new ByteArrayInputStream(bytes, offfset, len))));
}
这样的话就可以实现应用层的buffer复用,而且实现反序列化的zero-copy.

不错的方法,阅读和重构开源项目的代码这值得我们学习。
复用buffer的话要注意同步问题,在deserialize()返回前确保buffer的内容不会被覆写才行。
比如:把deserialize()和写入buffer的操作放在2个线程中就会造成问题。
恩,这个方法不错,对于java初学者来说需要注意内存多次拷贝来提高效率
我有几点建议:
1.代码是为了某个功能,应该有入口函数,入口函数我认为最好简单一些,最好就是顺序的调用其他接口,这个入口函数应该尽量放到类的最上面;这个和上面的代码风格之后的最后一种相似;
2.关于函数的编写方式我个人偏好下面的方式:
void fun(void)
{
code….
}
原因是:函数是一个功能的载体,函数名应当是功能的描述者,函数体应当是功能的实现者。我觉得函数名和函数体应当有意识的分块。
函数体有开始和结束:开始为”{“,单独一行;结束为”}”,单独一行;
3.我认为if语句本身是一条指令,if是操作符,if可以控制的代码是操作数,我更倾向把操作数放在{}内部(即使只有一行)。这样我们在读if语句就不会有两种情况:有{}和没有{}.我觉得代码本身的目的是表达需求的二义性,而不是代码本身的二义性。
not fun.