深入拆解Tomcat & Jetty
李号双
eBay技术主管
立即订阅
6067 人已学习
课程目录
已完结 44 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | Java程序员如何快速成长?
免费
模块一 必备基础 (4讲)
01 | Web容器学习路径
02 | HTTP协议必知必会
03 | 你应该知道的Servlet规范和Servlet容器
04 | 实战:纯手工打造和运行一个Servlet
模块二 整体架构 (9讲)
05 | Tomcat系统架构(上): 连接器是如何设计的?
06 | Tomcat系统架构(下):聊聊多层容器的设计
07 | Tomcat如何实现一键式启停?
08 | Tomcat的“高层们”都负责做什么?
09 | 比较:Jetty架构特点之Connector组件
10 | 比较:Jetty架构特点之Handler组件
11 | 总结:从Tomcat和Jetty中提炼组件化设计规范
12 | 实战:优化并提高Tomcat启动速度
13 | 热点问题答疑(1):如何学习源码?
模块三 连接器 (9讲)
14 | NioEndpoint组件:Tomcat如何实现非阻塞I/O?
15 | Nio2Endpoint组件:Tomcat如何实现异步I/O?
16 | AprEndpoint组件:Tomcat APR提高I/O性能的秘密
17 | Executor组件:Tomcat如何扩展Java线程池?
18 | 新特性:Tomcat如何支持WebSocket?
19 | 比较:Jetty的线程策略EatWhatYouKill
20 | 总结:Tomcat和Jetty中的对象池技术
21 | 总结:Tomcat和Jetty的高性能、高并发之道
22 | 热点问题答疑(2):内核如何阻塞与唤醒进程?
模块四 容器 (8讲)
23 | Host容器:Tomcat如何实现热部署和热加载?
24 | Context容器(上):Tomcat如何打破双亲委托机制?
25 | Context容器(中):Tomcat如何隔离Web应用?
26 | Context容器(下):Tomcat如何实现Servlet规范?
27 | 新特性:Tomcat如何支持异步Servlet?
28 | 新特性:Spring Boot如何使用内嵌式的Tomcat和Jetty?
29 | 比较:Jetty如何实现具有上下文信息的责任链?
30 | 热点问题答疑(3):Spring框架中的设计模式
模块五 通用组件 (4讲)
31 | Logger组件:Tomcat的日志框架及实战
32 | Manager组件:Tomcat的Session管理机制解析
33 | Cluster组件:Tomcat的集群通信原理
特别放送 | 如何持续保持对学习的兴趣?
模块六 性能优化 (8讲)
34 | JVM GC原理及调优的基本思路
35 | 如何监控Tomcat的性能?
36 | Tomcat I/O和线程池的并发调优
37 | Tomcat内存溢出的原因分析及调优
38 | Tomcat拒绝连接原因分析及网络优化
39 | Tomcat进程占用CPU过高怎么办?
40 | 谈谈Jetty性能调优的思路
41 | 热点问题答疑(4): Tomcat和Jetty有哪些不同?
结束语 (1讲)
结束语 | 静下心来,品味经典
深入拆解Tomcat & Jetty
登录|注册

20 | 总结:Tomcat和Jetty中的对象池技术

李号双 2019-06-25
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;
}
}
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Tomcat & Jetty 》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(13)

  • 802.11
    工厂模式和池化思想有什么区别呢

    作者回复: 工厂模式没有一个池来存对象,并且侧重不同,工厂模式是设计上的考虑,不是性能方面的

    2019-06-27
    2
  • Wiggle Wiggle
    “并且它本身只支持扩容不支持缩容,也就是说数组对象在使用过程中不会被重新赋值,也就不会被 GC”。这句话是不是写错了?我觉得是不是想说【数组元素】在使用过程中不会被重新赋值?因为扩容的话,创建了新的数组;缩容的话反而不用创建新的数组
    2019-08-26
    1
  • 清风
    也看了些书上的讲解,看完后还是没有像老师这样能总结出一个清晰的逻辑结构,这样的情况需要怎么办呢

    作者回复: 可以从why what how 整理一下思路

    2019-07-01
    1
    1
  • 掐你小77
    老师,你说的:“对象一旦归还给对象池,使用者就不能对它做任何操作了”,是一种默认的编码规范么?一种口头约束:即使用者不应该再持有这个对象引用对对象做一些操作,避免造成一些线程安全问题。可以这样理解么?
    2019-10-14
  • X中倪
    老师 我有一个疑问 池化。对象池 、线程池 、数据库连接池等等 他们都是如出一辙吗?还是大同小异

    作者回复: 基本思想都一样

    2019-09-16
  • 星辰
    同步栈有看到,但是不知道它是做池化用的 😂😂😂

    线程池 里面维护了线程数组和任务队列
    连接池
    jvm的常量池 ?

    作者回复: 常量池也是一种池化

    2019-08-15
  • z.l
    赞,如果能有jetty和netty对象池实现的对比就更好了
    2019-06-27
  • kyon
    您好,请问 ArrayByteBufferPool 中,direct 和 indirect 都是 new 出来的,区别是什么?另外在 new ByteBufferPool.Bucket(this,size,_maxQueue) 中,参数 _maxQueue 的作用是什么?

    作者回复: APR那篇有详细解释,HeapByteBuffer与DirectByteBuffer的区别。

    maxqueue 的作用是控制内存池的总大小

    2019-06-26
  • TJ
    为什么tomcat不使用java本身的stack class? 它也是基于数组的。自己再加一个同步就可以了

    作者回复: java本身的stack是不是实现上有点复杂,这里要尽量简单

    2019-06-25
  • WL
    请问老师Tomcat为什么用栈做对象池,那要去栈底的对象不是很麻烦很不灵活吗?为啥不用map的方式呢?

    作者回复: 不会要去栈底找对象的情况,对象都是无差别的

    2019-06-25
    1
  • -W.LI-
    我之前听人说事务里面的数据库链接就是通过threadLocal来共享的(事务结束后会从threadlocal删除当前链接么?)。那这个数据库的连接如果和Tomcat的线程数一对一绑定上能提高效率么?
    2019-06-25
  • -W.LI-
    老师好学到了。通过threadlocal来减少锁竞争上下文切换的开销。
    可是我看见好多帖子说threadlocal容易内存泄露啥的肯比较多需要慎用。五年码龄从没用过😂。
    请教一个问题threadLocal中的对象如果用完不清。下次别的请求Tomcat线程池中拿到同个线程,能取到之前请求存入的数据么?

    作者回复: 会的,所以要及时清理

    2019-06-25
    1
  • Liam
    tomcat和jetty的对象池没有空闲超时/超量回收的机制吗?

    作者回复: 似乎没有,对象池大小靠连接数限制

    2019-06-25
收起评论
13
返回
顶部