在线程池环境下使用ThreadLocal与内存池露
线程池会保留一部分空闲线程仍然存活。如果处理ThreadLocal变量的线程是由线程池维护的,在某些情况下(例如ThreadLocal<T>的T是个大对象),有必要使用ThreadLocal.remove()手工清除ThreadLocal中的内容以释放其占用的内存空间。
Tomcat6使用NIO后对ThreadLocal的影响
很早就听说tomcat6使用nio了,这几天突然想到一个问题,使用nio代替传统的bio,ThreadLocal岂不是会存在冲突?
首先,何谓nio?
如果读者有socket的编程基础,应该会接触过堵塞socket和非堵塞socket,堵塞socket就是在accept、read、write等IO操作的的时候,如果没有可用符合条件的资源,不马上返回,一直等待直到有资源为止。而非堵塞socket则是在执行select的时候,当没有资源的时候堵塞,当有符合资源的时候,返回一个信号,然后程序就可以执行accept、read、write等操作,这个时候,这些操作是马上完成,并且马上返回。而windows的winsock则有所不同,可以绑定到一个EventHandle里,也可以绑定到一个HWND里,当有资源到达时,发出事件,这时执行的io操作也是马上完成、马上返回的。一般来说,如果使用堵塞socket,通常我们时开一个线程accept socket,当有socket链接的时候,开一个单独的线程处理这个socket;如果使用非堵塞socket,通常是只有一个线程,一开始是select状态,当有信号的时候马上处理,然后继续select状态。
按照大多数人的说法,堵塞socket比非堵塞socket的性能要好。不过也有小部分人并不是这样认为的,例如Indy项目(Delphi一个比较出色的网络包),它就是使用多线程+堵塞socket模式的。另外,堵塞socket比非堵塞socket容易理解,符合一般人的思维,编程相对比较容易。
nio其实也是类似上面的情况。在JDK1.4,sun公司大范围提升Java的性能,其中NIO就是其中一项。Java的IO操作集中在java.io这个包中,是基于流的阻塞API(即BIO,Block IO)。对于大多数应用来说,这样的API使用很方便,然而,一些对性能要求较高的应用,尤其是服务端应用,往往需要一个更为有效的方式来处理IO。从JDK 1.4起,NIO API作为一个基于缓冲区,并能提供非阻塞O操作的API(即NIO,non-blocking IO)被引入。
BIO与NIO一个比较重要的不同,是我们使用BIO的时候往往会引入多线程,每个连接一个单独的线程;而NIO则是使用单线程或者只使用少量的多线程,每个连接共用一个线程。
这个时候,问题就出来了:我们非常多的java应用是使用ThreadLocal的,例如JSF的FaceContext、Hibernate的session管理、Struts2的Context的管理等等,几乎所有框架都或多或少地应用ThreadLocal。如果存在冲突,那岂不惊天动地?
后来终于在Tomcat6的文档(http://tomcat.apache.org/tomcat-6.0-doc/aio.html)找到答案。根据上面说明,应该Tomcat6应用nio只是用在处理发送、接收信息的时候用到,也就是说,tomcat6还是传统的多线程Servlet,我画了下面两个图来列出区别:
tomcat5:客户端连接到达 -> 传统的SeverSocket.accept接收连接 -> 从线程池取出一个线程 -> 在该线程读取文本并且解析HTTP协议 -> 在该线程生成ServletRequest、ServletResponse,取出请求的Servlet -> 在该线程执行这个Servlet -> 在该线程把ServletResponse的内容发送到客户端连接 -> 关闭连接。
我以前理解的使用nio后的tomcat6:客户端连接到达 -> nio接收连接 -> nio使用轮询方式读取文本并且解析HTTP协议(单线程) -> 生成ServletRequest、ServletResponse,取出请求的Servlet -> 直接在本线程执行这个Servlet -> 把ServletResponse的内容发送到客户端连接 -> 关闭连接。
实际的tomcat6:客户端连接到达 -> nio接收连接 -> nio使用轮询方式读取文本并且解析HTTP协议(单线程) -> 生成ServletRequest、ServletResponse,取出请求的Servlet -> 从线程池取出线程,并在该线程执行这个Servlet -> 把ServletResponse的内容发送到客户端连接 -> 关闭连接。
从上图可以看出,BIO与NIO的不同,也导致进入客户端处理线程的时刻有所不同:tomcat5在接受连接后马上进入客户端线程,在客户端线程里解析HTTP协议,而tomcat6则是解析完HTTP协议后才进入多线程,另外,tomcat6也比5早脱离客户端线程的环境。
实际的tomcat6与我之前猜想的差别主要集中在如何处理servlet的问题上。实际上即使抛开ThreadLocal的问题,我之前理解tomcat6只使用一个线程处理的想法其实是行不同的。大家都有经验:servlet是基于BIO的,执行期间会存在堵塞的,例如读取文件、数据库操作等等。tomcat6使用了nio,但不可能要求servlet里面要使用nio,而一旦存在堵塞,效率自然会锐降。
所以,最终的结论当然是tomcat6的servlet里面,ThreadLocal照样可以使用,不存在冲突。
分享到:
相关推荐
在NIO实现中,我们需要考虑如何在非阻塞环境中有效地处理会话。 8. **异常处理**:为了保证服务的稳定性,我们需要设计一套完整的异常处理机制,确保任何错误都能被正确捕获和处理。 9. **性能优化**:手写Tomcat ...
APR协议的Connector利用本地库,能够提供更好的性能,特别是在高并发环境下,它更适合运行需要高性能的Web应用。 在server.xml配置文件中,元素的protocol属性可以指定Connector使用的协议。如果没有指定protocol,...
用户可以通过解压此文件,直接在Windows x64环境下部署并运行Tomcat服务器,或者研究优化配置以获取灵感。 总的来说,这个Tomcat版本是针对性能和稳定性的深度定制,尤其适合需要高并发处理和优化日志输出的场景。...
3-5Tomcat响应请求源码与nio处理请求源码实现.mp4
tomcat默认的 HTTP connector 是阻塞的,并且每个连接对应一个线程。这会造成线程资源的浪费,因为连接本身可能不一定频繁被使用,而是仅仅被用来k
此版本在Tomcat7.0.69 的基础上...2、 启用nio 和 线程池配置 (server.xml) 3、修改了context.xml ,添加redis 支持(注意redis 连接密码) 4、在Root目录添加了test.jsp 用于查看多tomcat集群时sessionId是否一直
在Java NIO框架下,这可能涉及到选用合适的缓存策略,比如使用ByteBuffer来存储待发送的数据,并通过SelectionKey的interestOps来标记哪些连接有未发送完的数据。 在项目实践中,还需要考虑错误处理和异常恢复,...
Jetty、Tomcat和Mina都是Java领域中著名的Web服务器和应用服务器,它们在NIO架构上有着相似的设计模式。本文将从这三个框架中提炼出NIO构架网络服务器的经典模式,并逐一解析它们的核心机制。 首先,Jetty的NIO实现...
目标环境Tomcat + JDK 使用 NIO/BIO 连接器进行 SSL。 在 Tomcat 7 + Java 7 / Tomcat 8 + Java 8 上测试,但写成 Tomcat 4.1 + JDK1.4.2 兼容。注意密码列表按推荐顺序排序。 接下来 Tomcat 将支持 Tomcat 8.0.21 /...
1. **性能优化**:Tomcat 8引入了更多性能优化,比如NIO2支持,改进的线程池管理等。 2. **HTTP/2支持**:Tomcat 8支持HTTP/2协议,提供更快的数据传输速度。 3. **WebSocket支持**:Tomcat 8原生支持WebSocket协议...
5. **线程模型**:Tomcat使用NIO或 APR(Apache Portable Runtime)提供非阻塞I/O,以提高性能。深入理解`Executor`接口和`ThreadPool`类,了解Tomcat如何管理线程池来处理并发请求。 6. **部署和热更新**:Tomcat...
3. NIO(非阻塞I/O)改进:Tomcat 7增强了NIO连接器,提高了服务器处理并发请求的能力,提升了性能。 4. 配置简化:引入了web.xml的注解配置,使得部署描述符的编写更为简洁。 5. 新的安全特性:增加了Secure ...
NIO模式下,Tomcat使用一个线程池处理多个连接,提高了并发性能。 五、Session管理 Tomcat提供了内置的Session管理,包括会话创建、有效期设置、会话跟踪、分布式环境下的会话复制等。默认情况下,Session信息存储...
Tomcat作为最常用的Java Web服务器,随着并发量越来越高,Tomcat的性能会急剧下降,那有没有什么方法来优化Tomcat在高并发环境下的性能呢? Tomcat运行模式 Tomcat的运行模式有3种。 1.bio模式 默认的模式,性能非常...
8. **NIO和APR连接器**:Tomcat 7.0提供了两种连接器选项,即NIO(非阻塞I/O)和APR(Apache Portable Runtime),用户可以根据需求选择更适合的连接器以优化性能。 9. **错误处理**:Tomcat 7.0改进了错误页面处理...
默认情况下,Tomcat并没有启用线程池功能。通过配置线程池,可以有效地管理请求处理线程的数量,避免频繁创建和销毁线程带来的开销,进而提高系统整体性能。 在`server.xml`文件中,可以配置名为`Executor`的元素来...
另外,Tomcat的NIO模式还支持EPoll(Linux系统特有的高效I/O选择器),进一步提升了在Linux环境下的性能。EPoll相比传统的Select和Poll,有更好的性能表现,尤其是面对大量文件描述符时。 总结起来,Java NIO在...
Tomcat7、Tomcat8和Tomcat9是不同版本的Tomcat,每个版本都有其特性和改进。 **Tomcat7**: Tomcat7是2011年发布的,它主要支持Java Servlet 3.0和JSP 2.2规范。这个版本引入了一些重要改进,包括增强的安全性、更...
6. **性能优化**:Tomcat 7通过内存管理和线程池的优化,提升了整体性能,特别是在高并发场景下。 7. **更好的可扩展性**:支持热部署,可以在不中断服务的情况下更新和部署新的Web应用程序。 8. **错误处理**:...
- **环境变量**:设置`CATALINA_HOME`环境变量指向Tomcat的安装目录。 - **启动与停止**:通过运行`bin/startup.sh`(Unix/Linux)或`bin/startup.bat`(Windows)来启动Tomcat,使用`shutdown.sh`或`shutdown.bat...