原文地址:http://tutorials.jenkov.com/java-performance/read-patterns.html

好久没翻译了,逛知乎,无意间发现的一个链接,写的太好了,而且内容也不多(博主有点懒了~),忍不住翻译下,希望园子的朋友可以一起学习

--------------------------------------------------------------我是华丽的分割线--------------------------------------------------------------

如何读取数据将很大程度影响你的java应用。在本篇文章中,我将介绍几种读取模式,并解释他们的性能特性

写到新对象中

第一种读模式叫做写到新的对象中。这种就是我们在大学学习中,被冠以"正确"的读取数据的一种典型方式。

读取新对象模式,有一个返回一个全新对象结构的方法,下面例子来说明:

public class MyData {
public int val1 = 0;
public int val2 = 0;
}

读取方法

public MyData readMyData(byte[] source) {
MyData myData = new MyData(); myData.val1 = source[0];
myData.val2 = source[1]; return myData;
}

正如我们所见,方法会返回一个MyData对象。首先,MyData对象会被先创建。其次,方法将数据写到创建好的MyData对象中,最后,方法返回创建好的这个对象

值得注意的是,每次调用readMyData()方法,都将创建一个全新的MyData对象。这也是为什么这种模式叫做写到新对象。

加入readMyData()方法被频繁的调用,那么他讲创建无数的MyData对象。这会被系统和垃圾回收器带来压力。结果也就导致性能低下,甚至可能时候造成垃圾回收中断。

另外一个写到新对象模式的劣势就是每个对象可能被存储在不同的内存区域。这也意味着CPU缓存的效率会很低。

读取到已存在对象

读取到已存在对象模式是从已有对象中读取对象来代替创建一个全新的对象。这也意味着相同的对象可以被重置和重复利用多次。让我们将上面的方法改成读取到已存在对象模式:

 public MyData readMyData(byte[] source, MyData myData) {

    myData.val1 = source[0];
myData.val2 = source[1]; return myData;
}

两种模式最主要的区别在于,方法参数中增加了MyData的对象参数。这样,我们可以让调用方法着决定是使用已有的对象还是重新创建一个新的对象。

相比于总是创建一个新的MyData,次模式可以减少MyData实例来节省时间和内存。同时对于垃圾回收造成的压力也更小。长时间垃圾回收中断的风险也会降低。

减少对象同时意味着滞留在CPU缓存中的机会比每次创建一个对象的模式来的更高。

从外部读取

从外部读取模式并不会将读取到的数据写到对象中。而是直接从底层数据中读取所需要的数据

直接从数据源读取数据可以节省一些时间,因为在它们(方法或则变量)在使用前,不需要赋值。当需要的时候,直接从底层数据源中拷贝值过来即可

这种方式还有一个优势在于实际需要多少数据,就拷贝多少,而不需要全部赋值

将上述的例子改造成这种模式,如下:

public class MyData() {

    private byte[] source = null;

    public MyData() {
} public void setSource(byte[] source) {
this.source = source;
} public int getVal1() {
return this.source[0];
} public int getVal2() {
return this.source[1];
}
}

然后,我们这样使用它

byte[] source = ... //get bytes from somewhere

MyData myData = new MyData();

myData.setSource(source);

int val1 = myData.getVal1();
int val2 = myData.getVal2();

首先注意到,我们仅仅通过改变source数组,就可以复用MyData实例。

其次,数据从数组字节中拷贝仅需要一次。

第三,当我们只需要部分值计算的时候,我们只需要调用其中任意一个方法,这样就节省了时间。除非是我们需要同时调用这两个方法

一个只读方法,并不知道有多少个变量值是需要被读取的。因此,通常的做法是将所有的值都拷贝到对象中。除非你定制多个计算方法,不过这样有增加了额外的工作量

导航

如果底层数据源包含了多个"记录"或则"对象",我们可以将从外部读取模式变成导航模式。导航模式的工作原理跟从外部读取类似,但是在方法上新增了从底层数据源中读取数据的导航

假设每个MyData对象由底层数据源中的两个字节组成,让我们先看下下面的例子:

public class MyData() {

    private byte[] source = null;
private int offset = 0; public MyData() {
} public void setSource(byte[] source, int offset) {
this.source = source;
this.offset = offset;
} public int getVal1() {
return this.source[this.offset];
} public int getVal2() {
return this.source[this.offset + 1];
} public void next() {
this.offset += 2; //2 bytes per record
} public boolean hasNext() {
this.offset < this.source.length;
}
}

首先改变的是setResource()方法新增了一个额外的参数offset。严格来说,offset是非必须的,但是它(offset)可以让我们读取数据的索引从默认的第一位改成offset定义的

第二个变化是getVal1()和getVal2()方法现在使用内部的offset变化作为读取数组的索引

第三个变化是新增了next()方法。next()方法会将内部的offset值加2,这样offset将指向下一条数组记录

第四个变化新增了hasNext()方法,该方法将返回数据源是否还有可供查询的数据记录。

你可以使用如下导航方法

byte[] source = ... // get byte array from somewhere

MyData myData = new MyData();
myData.setSource(source, 0); while(myData.hasNext()) {
int val1 = myData.getVal1();
int val2 = myData.getVal2(); myData.next();
}

正如你所看到的,使用导航模式是相关直观的。非常镜像于java标准的迭代器

java 高性能读模式(译)的更多相关文章

  1. JAVA NIO non-blocking模式实现高并发服务器(转)

    原文链接:JAVA NIO non-blocking模式实现高并发服务器 Java自1.4以后,加入了新IO特性,NIO. 号称new IO. NIO带来了non-blocking特性. 这篇文章主要 ...

  2. JAVA NIO non-blocking模式实现高并发服务器

    JAVA NIO non-blocking模式实现高并发服务器 分类: JAVA NIO2014-04-14 11:12 1912人阅读 评论(0) 收藏 举报 目录(?)[+] Java自1.4以后 ...

  3. DCL实现多线程安全的高性能懒汉模式

    DCL实现多线程安全的高性能懒汉模式 1.单线程安全的懒汉模式实现 源码: private static LazyLoad instance = null; public static LazyLoa ...

  4. java多线程-读写锁

    Java5 在 java.util.concurrent 包中已经包含了读写锁.尽管如此,我们还是应该了解其实现背后的原理. 读/写锁的 Java 实现(Read / Write Lock Java ...

  5. Java设计模式——组合模式

    JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...

  6. java装饰者模式理解

    java 装饰者模式其实就是扩展子类的功能,和继承是一个性质. 但继承是在编译时就固定扩展了父类的一些功能,而装饰者模式是在运行过程中动态绑定对象,实现一个子类可以随时扩展功能. 将方法排列组合,也可 ...

  7. !!转!!java 简单工厂模式

    举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人话说:“天地开辟,未有人民,女娲抟土为人.”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面.女娲造人,这就是 ...

  8. java 双重检查模式

    java 双重检查模式 在并发环境下 兼顾安全和效率 成例(Idiom)是一种代码层次上的模式,是在比设计模式的层次更具体的层次上的代码技巧.成例往往与编程语言密切相关.双重检查成例(Double C ...

  9. Java 抽象工厂模式

    抽象工厂模式(Abstract Factory Pattern)是工厂方法模式的进一步抽象,其英文原话"Provide an interface for creating families ...

随机推荐

  1. MongoDB数据库遭大规模勒索攻击,被劫持26000多台服务器 #精选GITHUBMYSQL

    昨天,一个大新闻爆出,MongoDB数据库叕被攻击了.就在上周末,三个黑客团伙劫持了MongoDB逾26000多台服务器,其中规模最大的一组超过22000台. “MongoDB启示录”再临?   此次 ...

  2. C#.NET常见问题(FAQ)-如何让listView如何选中一行

    把FullRowSelect设置为True     更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com/acetaohai123   我的在线论坛: ht ...

  3. 用javascript请求动态页url返回更新

    例如我们用Ajax请求一个动态页返回的信息,或一个图片验证码请求一个*.ashx页面,第一次请求没问题,而第二次请求时,不变化,为啥? 因为第二次及以后请求的url与第一次是一样的,所以服务器(或是浏 ...

  4. robot framework-requests库安装过程问题解决

    这几天本想研究下用robotframework+HTTP library (Requests)来做接口测试(http协议), 安装完Requests库后,在RIDE里导入该库时显示是红色,即导入失败( ...

  5. 微信小程序 - setData:key的几种用法

    1. 常量key渲染   2. 变量key渲染(字符串和变量先拼接) 3.对象key渲染

  6. 机器学习-分类器-级联分类器训练(Train CascadeClassifier )

    一.简介: adaboost分类器由级联分类器构成,"级联"是指最终的分类器是由几个简单分类器级联组成.在图像检测中,被检窗口依次通过每一级分类器,这样在前面几层的检测中大部分的候 ...

  7. 016-Go Iris Restful测试

    1:data/data.go package data import( "fmt" "database/sql" _"github.com/lib/p ...

  8. 如何解析android访问webservice返回的SoapObject数据(可用)

    怎么解析android访问webservice返回的SoapObject数据 本帖最后由 kkDragon123 于 2013-03-26 15:50:07 编辑 我的数据如下:mingdanResp ...

  9. oracle数据库,怎么给已有数据的表添加自增字段

    场景:数据仓库,ODI为使用Oracle Incremental Update IKM,需要对一事实表增加主键. 思想:基于老表创建新表,添加自增字段(序列+触发器实现),把老数据导入新表,删除老表, ...

  10. Java之创建对象>7.Avoid finalizers

    1.Finalizers are unpredictable, often dangerous, and generally unnecessary. 2.never do anything time ...