浅聊Tomcat线程池

正确的应用场景+合适的线程数量 = 快速运行速度

Tomcat是目前比较流行的 Web 容器,接受请求之后都会转交给线程池处理,这样可以有效提高处理的能力与并发度

 

经典老题: 创建线程池时应该给多大的核心线程数,最大线程数?

抛开场景谈线程数都是耍流氓,

场景的话 一般分为IO密集型与CPU密集型,也就是线程的大部分时间将用来计算还是等待IO

一个原则就是,如果IO密集型,线程大部分时间用来等待IO结果,例如查数据库这种操作,线程等待IO结果CPU是空闲可以处理其他事情的,这样场景鼓励多创建线程并发执行

如果是CPU密集型,线程大部分时间在执行CPU计算,一般创建这种 线程数 = CPU核心数+1即可 (+1是为了当线程运行后出问题,CPU有空闲可以额外处理一个线程)  这种场景就算创建再多的线程CPU也来不及执行,与线程数大致比例 1:1

 

为什么Tomcat不用JDK原生线程池?

想一想原生线程池的提交一个任务的运行过程

浅聊Tomcat线程池

 

 

总体的策略就是先让核心线程数的线程干活,多余的任务统统塞到阻塞队列,阻塞队列塞不下才再多创建线程来干活, 

这种情况下当大量请求提交后,很可能大量的请求都会被阻塞在队列中 而线程还没有创建到最大线程数,导致用户请求处理很慢 用户体验很差,用户蚌埠住了、

 

有个解决办法就是我直接把核心线程数set一个最大值,和最大线程数一样的值,这样不就先可着线程最大能力去处理,是在处理不过来再进队列吗。

这样是可以做到,但是也就意味着创建的线程都是核心线程,那么多核心线程创建完了当没任务干的时候,那不是妥妥的浪费资源吗?

 

 

Tomcat线程池是如何做的?

简单的说

1.新线程池继承JDK线程池接口,重写了execute()方法

重写了execute()方法,当抛出拒绝策略了 再给一次机会,尝试往阻塞队列里插任务,尽最大努力的去执行任务 (意思是不抛弃不放弃,免得用户请求失败哭唧唧)

 

2.新阻塞队列继承了LinkedBlockingQueue,重写了offer()方法

 

重写了offer()方法,每次向队列插入任务,判断如果当前线程数小于最大线程数则插入失败。进而逼线程池创建新线程来处理任务 (意思你别想偷懒,把任务丢到队列就不管了)

 

 

最后闲着也是闲着

计算一下一台8核cpu的机器上,tomcat线程池应该配置多大? 每秒能处理多少请求?

(假如机器不运行其他进程,没有其他线程会占用cpu资源)

(假设每个请求查数据库IO时间大概是100ms)

(假设每个请求cpu计算时间大概是10ms)

如果单线程只会占用cpu10ms,剩下等待IO时间100ms,

先按单核cpu来算,那也就是第一个请求会占用cpu10ms,然后就会去等IO。然后cpu处理第二个请求10ms,然后再处理第三个请求10ms,第四个,第五个....

当处理完第11个的时候第一个请求的IO结束,请求完成 。当1秒钟结束时cpu处理了100个请求的计算,其中90个已经IO完毕返回结果。

cpu同时可以处理十个请求,8核cpu同时可以处理80个请求,就会差不多支持900请求/s

浅聊Tomcat线程池

上一篇:PC和移动端自动识别


下一篇:关于 vue-cli 使用 postcss-px-to-viewport 使移动端自适应