问题描述
我在github中使用CompletableFuture使用了this sample。
我尝试同时从浏览器(chrome)的多个选项卡运行/ asyncCompletable端点。 关键是因为Tomcat是Servlet容器,并且它具有自己的Servlet线程池,因此从浏览器的不同选项卡访问相同的端点url不一定需要使用相同的主线程。请在下面查看我的控制台日志:
8:07:07.334 [http-nio-9191-exec-8] Request received
18:07:07.335 [http-nio-9191-exec-8] Servlet thread released
18:07:07.335 [ForkJoinPool.commonPool-worker-3] Start processing request
18:07:08.262 [http-nio-9191-exec-7] Request received
18:07:08.262 [http-nio-9191-exec-7] Servlet thread released
18:07:08.262 [ForkJoinPool.commonPool-worker-4] Start processing request
18:07:08.860 [http-nio-9191-exec-9] Request received
18:07:08.861 [http-nio-9191-exec-9] Servlet thread released
18:07:08.861 [ForkJoinPool.commonPool-worker-5] Start processing request
18:07:09.376 [http-nio-9191-exec-10] Request received
18:07:09.377 [http-nio-9191-exec-10] Servlet thread released
如您所见,对于同一URL,每个浏览器选项卡都使用不同的线程,而不是将释放的线程用于以后的调用。 我的意思是,它不会为下一个传入请求重用已释放的线程(例如http-nio-9191-exec-7)。 为什么呢?
解决方法
线程池就是它所说的-一个池。因此,不能保证在池中重新为任务分配相同的线程,这也无济于事。池仅返回池中的下一个可用线程。但是“下一个”是什么意思?这取决于池的实现-应该从用户那里抽象出来。仅仅因为它没有直接重新分配下一个请求并不意味着它永远不会被重用。池决定如何执行此操作。这取决于池的策略。因此,Servlet池中可能会有一些裕度或时间阈值或一些队列。
您可以尝试在出于评估目的重新配置Tomcat时,是否改变行为:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="0"/>
但是,这不会对性能有帮助,因此不建议这样做。除非有充分的理由,否则我不会惹恼Servlet线程池机制。池是出于良好的理由移交该控件的。