概述
一个对象的生命周期大致包括三个阶段:对象的创建、对象的使用、对象的销毁。因此对象的声明周期长度可用如下表达式表示: T=T1+T2+T3,其中T1为对象的创建时间,T2为对象的使用时间,T3为对象的销毁时间,其中T2为真正有效的使用时间,而T1,T3为对象本身开销。Java采用GC对内存进行管理,当GC开始进行“垃圾对象”回收时,系统会暂停应用程序的执行。为了改善应用程序的性能,一方面应尽量减少对象的创建,延长对象的生命周期,另一方面还要尽量减少T1,T3的时间,而这些都可以通过池化技术来实现。Java中常见的池有对象池、线程池、连接池。
为什么要使用池
无论对象池、线程池还是连接池,它们大都先将一些创建好的对象缓存起来,放入池(容器)中。等到要使用的时候,是从池中取出,而不是新创建。这样,很大程度上能减少创建对象和销毁对象的时间开销,同时能使对象得到复用,提高了应用程序性能。
哪些对象需要使用池存储
随着计算机性能在各方面的提高,创建一个新的对象已经不像过去那样昂贵了。然而,有些对象,还是需要创建管理这些对象的池,使得这些对象能够动态的重用,而客户端代码也不用关心它们的生命周期,这样对提高应用程序性能还是有很大改善的。
- 创建的开销还是十分大的对象,比如线程、网络连接(数据库连接或socket连接)等一些非轻量级的对象。
- 使用过于频繁的对象,比如包装类对象。
Java中那些常见的池
- 对象池:包装类、Netty的缓冲区的创建
- 连接池:数据库连接、客户端创建socket连接,一般为长连接
- 线程池:JDK中线程的创建
对象池
- 包装类对象的缓存原理,以Integer类型对象的实现说明
在Java中,数据类型可以分为两大类,基本数据类型和引用数据类型,基本数据类型的数据不是对象,所以对于要将基本数据类型作为对象来使用的情况,需要使用其相对应的包装类。基础数据类型与包装数据类型相互转换通过包装类的自动装箱和拆箱机制来实现的。JDK5引入的自动装箱和拆箱就是编译器来依据我们编写的代码,决定是否进行装箱和拆箱动作,即无需使用valueOf()和intValue()等方法。自动装箱过程其实时调用了valueOf()的方法。 - valueOf()方法的源码为:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty<