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;


}


}