正确的应用场景+合适的线程数量 = 快速运行速度
Tomcat是目前比较流行的 Web 容器,接受请求之后都会转交给线程池处理,这样可以有效提高处理的能力与并发度
经典老题: 创建线程池时应该给多大的核心线程数,最大线程数?
抛开场景谈线程数都是耍流氓,场景的话 一般分为IO密集型与CPU密集型,也就是线程的大部分时间将用来计算还是等待IO一个原则就是,
如果IO密集型,线程大部分时间用来等待IO结果,例如查数据库这种操作,线程等待IO结果CPU是空闲可以处理其他事情的,这样场景鼓励多创建线程并发执行
如果是CPU密集型,线程大部分时间在执行CPU计算,一般创建这种 线程数 = CPU核心数+1即可 (+1是为了当线程运行后出问题,CPU有空闲可以额外处理一个线程) 这种场景就算创建再多的线程CPU也来不及执行,与线程数大致比例 1:1
1.为什么Tomcat不用JDK原生线程池?
想一想原生线程池的提交一个任务的运行过程
总体的策略就是先让核心线程数的线程干活,多余的任务统统塞到阻塞队列,阻塞队列塞不下才再多创建线程来干活, 这种情况下当大量请求提交后,很可能大量的请求都会被阻塞在队列中 而线程还没有创建到最大线程数,导致用户请求处理很慢 用户体验很差,用户蚌埠住了、有个解决办法就是我直接把核心线程数set一个最大值,和最大线程数一样的值,这样不就先可着线程最大能力去处理,是在处理不过来再进队列吗。
这样是可以做到,但是也就意味着创建的线程都是核心线程,那么多核心线程创建完了当没任务干的时候,那不是妥妥的浪费资源吗?
2.Tomcat线程池是如何做的?
简单的说
1.新线程池继承JDK线程池接口,重写了execute()方法
重写了execute()方法,当抛出拒绝策略了 再给一次机会,尝试往阻塞队列里插任务,尽最大努力的去执行任务 (意思是不抛弃不放弃,免得用户请求失败哭唧唧)
2.新阻塞队列继承了LinkedBlockingQueue,重写了offer()方法
重写了offer()方法,每次向队列插入任务,判断如果当前线程数小于最大线程数则插入失败。进而逼线程池创建新线程来处理任务 (意思你别想偷懒,把任务丢到队列就不管了)