20 | 总结:Tomcat和Jetty中的对象池技术
Posted IT编程学习栈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20 | 总结:Tomcat和Jetty中的对象池技术相关的知识,希望对你有一定的参考价值。
Java 对象,特别是一个比较大、比较复杂的 Java 对象,它们的创建、初始化和 GC 都需要耗费 CPU 和内存资源,为了减少这些开销,Tomcat 和 Jetty 都使用了对象池技术。所谓的对象池技术,就是说一个 Java 对象用完之后把它保存起来,之后再拿出来重复使用,省去了对象创建、初始化和 GC 的过程。对象池技术是典型的以空间换时间的思路。
由于维护对象池本身也需要资源的开销,不是所有场景都适合用对象池。如果你的 Java 对象数量很多并且存在的时间比较短,对象本身又比较大比较复杂,对象初始化的成本比较高,这样的场景就适合用对象池技术。比如 Tomcat 和 Jetty 处理 HTTP 请求的场景就符合这个特征,请求的数量很多,为了处理单个请求需要创建不少的复杂对象(比如 Tomcat 连接器中 SocketWrapper 和 SocketProcessor),而且一般来说请求处理的时间比较短,一旦请求处理完毕,这些对象就需要被销毁,因此这个场景适合对象池技术。
Tomcat 的 SynchronizedStack
Tomcat 用 SynchronizedStack 类来实现对象池,下面我贴出它的关键代码来帮助你理解。
public class SynchronizedStack<T> {
// 内部维护一个对象数组, 用数组实现栈的功能
private Object[] stack;
// 这个方法用来归还对象,用 synchronized 进行线程同步
public synchronized boolean push(T obj) {
index++;
if (index == size) {
if (limit == -1 || size < limit) {
expand();// 对象不够用了,扩展对象数组
} else {
index--;
return false;
}
}
stack[index] = obj;
return true;
}
// 这个方法用来获取对象
public synchronized T pop() {
if (index == -1) {
return null;
}
T result = (T) stack[index];
stack[index--] = null;
return result;
}
// 扩展对象数组长度,以 2 倍大小扩展
private void expand() {
int newSize = size * 2;
if (limit != -1 && newSize > limit) {
newSize = limit;
}
// 扩展策略是创建一个数组长度为原来两倍的新数组
Object[] newStack = new Object[newSize];
// 将老数组对象引用复制到新数组
System.arraycopy(stack, 0, newStack, 0, size);
// 将 stack 指向新数组,老数组可以被 GC 掉了
stack = newStack;
size = newSize;
}
}
复制代码以上是关于20 | 总结:Tomcat和Jetty中的对象池技术的主要内容,如果未能解决你的问题,请参考以下文章
总结:Apache/Tomcat/JBOSS/Jetty/Nginx区别 .
Day703.Tomcat I/O和线程池的并发调优 -深入拆解 Tomcat & Jetty