在javaweb当中,servlet在运行阶段,针对每个客户端的请求,都会创建一个线程,该线程调用servlet的实例?

如题所述

具体servlet的请求处理,这个是分配给线程池线程处理的,servlet容器都这样实现,这个没什么问题。我主要来说说其它的。

线程池的作用

从其他人的回答看,都是太高看线程池本身的作用了。

线程池作为一种资源池(这里的资源就是线程了)模型,最大的优点是重复利用已经创建的线程,避免线程的反复创建和销毁带来的处理器和内存的消耗。而除此之外,它需要配合其它机制才能发挥更大的作用。

请求到达服务器后,如果线程池没有可用线程,请求会进入队列排队,如果超过队列最大阈值会被丢弃。重点来了,如果你的请求处理服务会有如数据库调用/远程服务调用的IO处理,而你用的阻塞模型,则这个线程在请求处理完成之前并不能返还到线程池供其它请求服务。这种长期占用线程的行为,会严重限制请求的并发。线程的有效利用率太低,大部分时间都在阻塞中,这个和你有没有线程池没有关系。所以要在高并发的情况下保证性能,重点是你的服务内部的使用异步IO避免阻塞。这样在你某个请求处于IO等待期间,当前线程可以返还给线程池继续提供服务。

(补充)

下面有朋友提到了请求队列,这里简单说下。

请求队列是所有服务器程序都会考虑和设计的一个机制,这样的机制实际上起缓冲层作用,避免服务器在请求过多时崩溃。以Tomcat为例,Connector中有下面几个关键配置。

acceptCount就是允许未处理请求队列的长度(backlog),默认是100,可以根据实际情况做调整。

更多的配置参见官方文档。如果有时间,会写一个Tomcat具体如何实现请求队列及它的处理文章。

请求响应

更友好的体验还要从客户端出发来考虑,如果你能缩短请求的处理时间,客户端体验是极好的,比如成都访问杭州阿里云服务器,空载来回大概40ms的时间,如果你的服务处理控制在10ms以内,请求在50ms就可以返回,是不是很舒服?当然如果是静态资源做CDN几ms就可以完成。

要缩短请求响应时间,可以从两方面入手:

1、将服务分解成多个可以并行处理的任务,这里的任务一般都会包含一个异步IO调用,然后并行执行。

2、将不影响响应结果的子任务异步处理,提前返回响应。比如推送消息,日志记录等。考虑一些极端的情况:在双11和秒杀场景,只有商品的库存处理是最核心的,这个环节处理完就可以结束本次处理,像支付这种繁琐的处理就可以延后,还有部分操作都可以放入异步队列继续处理。

将请求分解异步并行化后,实际上又会多出很多线程切换,这个时候线程池的作用就被放大了。

总结

仅仅有线程池而没有异步并行框架的支撑,线程池其实只能发挥很小的作用,在高并发情况下它必不可少,但非最核心的那个东西。我们一般的Web应用都是IO密集型的,只要保证服务内的IO都异步化,线程池只需非常少量的线程就可以应对大量并发。

温馨提示:答案为网友推荐,仅供参考
相似回答