通常人们认识的序列化类实现java.io.Serializable 像这样:
import java.io.*;
public class Pojo implements Serializable {
private static final long serialVersionUID = L;
....
}
这种做法被广大程序员广泛应用,然而这种序列化的性能很低。它使用反射机制寻找序列化类的类变量和这些类变量的类型。大家都知道反射是一个非常消耗时间的处理过程。
我们如何能尽可能的在程序中减轻这种负载呢?有下面三种方法:
1.使用ObjectStreamField类
2.使用readObject / writeObject 方法
3.使用Externalizable 接口
在上面的方法中,性能最好的是使用Externalizable 接口。为了便于理解,将为不同的方法例举一个例子。
ObjectStreamField 类为序列化机制提供序列化对象的成员变量以及成员变量的类型。这样做的好是可以节约一部分时间,他不必通过反射机制去查询成员变量以及类型。关键字transient 仍然可以在这种方式下正常使用,不过在创建ObjectStreamField对象添加序列话成员变量的时候,剔除transient 标识的成员变量。
public class Pojo implements Serializable {
private static final long serialVersionUID = 1L;
private String valueA = "SomeTextA";
private int valueB = 10;
private float valueC = 100f;
private double valueD = 100.100d;
private short valueE = 10;
// Getters and setters go here.
private static final ObjectStreamField[] serialPersistFields = {
new ObjectStreamField("valueA", String.class),
new ObjectStreamField("valueB", Integer.class),
new ObjectStreamField("valueC", Float.class),
new ObjectStreamField("valueD", Double.class),
new ObjectStreamField("valueE", Short.class)
};
}
就像你所看到的,为了提升性能得必须指明你所序列化的成员变量,当然除了transient 的成员变量。
第二种方法是使用readObject / writeObject 方法。
public class Pojo implements Serializable {
private static final long serialVersionUID = 1L;
private String valueA = "SomeTextA";
private int valueB = 10;
private float valueC = 100f;
private double valueD = 100.100d;
private short valueE = 10;
// Getters and setters go here.
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.writeUTF(valueA);
oos.writeInt(valueB);
oos.writeFloat(valueC);
oos.writeDouble(valueD);
oos.writeShort(valueE);
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
this.valueA = ois.readUTF();
this.valueB = ois.readInt();
this.valueC = ois.readFloat();
this.valueD= ois.readDouble();
this.valueE= ois.readShort();
}
}
这种方式包括了序列化的序列化和反序列化过程。就像上面所展示的,仍然需要声明Serializable 接口。
第三种方式使用Externalizable 接口。
public class Pojo implements Externalizable {
private static final long serialVersionUID = 1L;
private String valueA = "SomeTextA";
private int valueB = 10;
private float valueC = 100f;
private double valueD = 100.100d;
private short valueE = 10;
// Getters and setters go here.
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(valueA);
out.writeInt(valueB);
out.writeFloat(valueC);
out.writeDouble(valueD);
out.writeShort(valueE);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.valueA = in.readUTF();
this.valueB = in.readInt();
this.valueC = in.readFloat();
this.valueD= in.readDouble();
this.valueE= in.readShort();
}
}
这种方式与readObject / writeObject 方式不同的是不再需要声明Serializable 接口, readObject / writeObject 方法使用ObjectOutput/ObjectInput 接口作为参数代理输入流输出流实现类,并且serialVersionUID 仍然可以使用。
下面将测试各种序列化方法所消耗的时间:
public class Run {
private static int TIMES = 500000;
public static void main(String[] args) {
Pojo sp = new Pojo();
long start = System.currentTimeMillis();
for (int i = 0; i<TIMES;i++){
serialize(sp);
}
long duration = System.currentTimeMillis() - start;
System.out.println("Externalizable: " + duration + "ms.");
}
public static void serialize(Pojo o) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bout);
out.writeObject(o);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
为了获得正确的测试结果,我们制定以下规则 。首先,不能测试一小部分对象,应该取较大的均值。第二,减小不必要的负载。如果测试程序快速产生大量的对象,会产生大量的垃圾收集。
在上面的代码中,我们仅序列化了50000个对象。并且没有将序列化的内容写入磁盘或者网络,因为会产生我们不希望的负载。
还有一点值得注意的是,如果有多个String类型的成员变量,他们之应该是不同的值。如果他们的值相同,那么他们引用的是同一个对象。
下面是不同jdk版本间的测试结果:
JDK 1.4.2_12
Serializable: 9766ms.
Streamfield: 9656ms.
Read/Write object: 7781ms.
Externalizable: 5875ms.
JDK 1.5.0_19
Serializable: 9016ms.
Streamfield: 8859ms.
Read/Write object: 7141ms.
Externalizable: 5610ms.
JDK 1.6.0 (B103)
Serializable: 7484ms.
Streamfield: 7312ms.
Read/Write object: 5610ms.
Externalizable: 4828ms.
有趣的是你可以发现使用Externalizable 接口提升了55%的性能。同时也可以看出jdk不同版本的垃圾收集器&Hotpot引擎性能也在提升!
分享到:
相关推荐
浅谈java中为什么实体类需要实现序列化 在Java中,实体类需要实现序列化是因为序列化是将对象转换为字节流的过程,而...因此,在设计实体类时,需要考虑实现Serializable接口,以便在需要时可以将其序列化和反序列化。
JAXB允许我们将Java类与XML Schema定义的元素和类型绑定,从而实现XML的序列化和反序列化。 在Java对象和XML之间的转换过程中,JAXB主要涉及到以下几个关键概念: 1. **Java类与XML Schema绑定**: JAXB使用`@...
它通过XML Schema或XML Mapping文件定义Java类与XML元素之间的映射关系,实现了XML数据的自动序列化和反序列化。 2. XML绑定与映射文件 在Castor中,映射文件通常以`.xml`扩展名,如`mapping.xml`,定义了Java类与...
标题 "Tomcat 使用 ...这个过程中涉及的关键点包括 Memcached 的安装和配置,以及 Tomcat 的 Manager 配置和序列化策略的选择。通过这样的设置,我们能有效提升系统的扩展性和可靠性,同时确保用户会话的一致性。
ObjectInputStream和ObjectOutputStream负责对象的序列化和反序列化操作。 7. **NIO(非阻塞I/O)** Java 1.4引入了NIO(New I/O)框架,提供了一种更有效率的I/O模型,特别是在多路复用I/O(Selector)方面。NIO...
1. **AjaxEngine**:这是DWR的核心,它负责处理JavaScript到Java的通信,包括序列化和反序列化、错误处理等。 2. **Caucho Hessian/Burlap**:DWR可以使用Hessian或Burlap作为传输协议,它们是轻量级的二进制/文本...
6. **输入/输出(I/O)**:Java的I/O流系统包括字符流和字节流,以及用于文件操作、网络通信和对象序列化的API。学会使用BufferedReader、FileWriter等类进行文件操作,是开发中常见的需求。 7. **网络编程**:Java...
- 代码优化:平衡性能与可读性,使用适当的编程技巧和工具。 - 多态与委派:在面向对象编程中,多态提供了动态绑定,委派用于委托任务给其他对象。 5. **算法与数据结构**: - 判断2的幂、奇偶性:基础算法应用...
- 实现`Serializable`接口以支持序列化。 #### 二、主方法与程序入口 **2.1 主方法** - 每个可执行的Java程序都应包含一个`main`方法作为入口点。 - 避免删除源代码中的`main`方法,即使在调试过程中也不应该移除...
ATMEGA128是一款由Atmel公司生产的高性能8位AVR微控制器,它具有丰富的片上资源,包括大量的程序存储器、数据存储器以及众多的I/O端口,适用于各种嵌入式应用,如数据采集系统。在这个项目中,我们看到它被用于采集...
设置伺服单元时,要对单元进行适当的配置,包括初始化设置和参数设置,这些设置决定了伺服驱动器的基本工作方式和性能表现。 接线与连接方面,需要按照手册中的指导,将伺服单元与电源及周边设备连接,保证电气连接...
9. **游戏数据持久化**:例如玩家的得分、进度等可能需要保存到本地或云端,涉及数据序列化和反序列化技术。 10. **版本控制**:"Jewel-master"可能表示这个项目是使用Git进行版本控制的,master分支通常是主分支,...
从pandas库的数据分析工具开始...撰写了大量与Python数据分析相关的经典文章,被各大技术社区争相转载,是Python和开源技术社区公认的权威人物之一。开发了用于数据分析的著名开源Python库――pandas,广获用户好评。
- **SVM参数选择**:在回归预测中,SVM的参数c和g的选择对模型性能至关重要。案例中提到要进行参数选择,通常通过交叉验证或网格搜索来找到最优的c和g值。 - **SVM模型训练**:使用归一化的`Low`数据训练SVM回归...
- **控制模式**:支持网络指令、脉冲序列和模拟指令。 #### 七、应用模式 - **配置文件位置模式**:控制器发送目标位置和速度,伺服放大器自动完成运动控制,简化了控制器的设计。 - **配置文件速度模式**、**配置...
这种方式通过构建一个对象,并将其作为data属性的值传递给$.ajax()方法,能够保证数据被正确序列化,并且符合Web服务对参数的解析需求。在使用对象字面量方式传递数据时,jQuery会自动将对象序列化成适合Web服务接收...
特征码是一种紧凑的数据表示形式,能够准确捕捉网页正文的关键信息,如最长公共子序列等,以最小化存储空间需求同时保持高精度。B-Tree作为一种自平衡树形数据结构,提供了高效的数据检索和插入能力,确保了特征码的...
9. **动画优化**:为了保证动画在各种设备上都能流畅运行,需要考虑文件大小和性能优化,例如减少不必要的细节,使用适当的压缩技术等。 通过以上知识点,我们可以了解到开门动画在网络资源中的应用和重要性,以及...