池化技术
在后端代码操作MySQL时,需要先与MySQL建立连接, 这个连接需要使用TCP的三次握手,比较的耗时,如果在正常的系统中,每一次执行sql,都要建立连接,连接使用完毕后断开连接,那么就会带来严重的性能影响。因此,池化技术就这样诞生了。
连接池基本配置
MySQL连接池有两个重要配置,最小连接数和最大连接数。
如果连接池中有空闲的连接,则直接使用这些已经建立好的连接,如果已有的连接数超过最小连接数,但是没有超过最大连接数,来了新的连接请求,则创建新的连接处理请求。如果当前连接数大于等于最大连接数,则让新的请求排队,如果超时则抛出错误。
还有一种情况是,当前连接池中的连接数小于最小连接数,那么新到的连接请求会直接创建新的连接,而不会使用池子中的连接。
针对于连接池中的连接,我们可以启动一个线程定期检测连接池是否可用,如果不可用就关闭该连接。
用线程池预先创建线程
jdk1.5中就提供了池化技术。ThreadPoolExecutor 就是其中的一种,它有两个参数coreThreadCount 和 maxThreadCount。
如果线程池中的线程数少于 coreThreadCount 时,处理新的任务时会创建新的线程;
如果线程数大于 coreThreadCount 则把任务丢到一个队列里面,由当前空闲的线程执行;
当队列中的任务堆积满了的时候,则继续创建线程,直到达到 maxThreadCount;
当线程数达到 maxTheadCount 时还有新的任务提交,那么我们就不得不将它们丢弃了。
流程如下图:

注意:JDK原生的线程池会优先把任务放进队列,而不是优先创建线程,这种就比较适合CPU密集型的任务。
因为CPU密集型的任务,如果创建过多的线程去执行任务,那么这些任务会争抢线程,导致频繁的上下文切换,造成性能的损失。
但是我们平时开发的web项目,其实属于I/O密集型的任务,因为牵扯到数据库,所以Tomcat就没有采用JDK自带的,而是做了改进,优先创建线程去处理请求。因为I/O密集型的大多时间都花费在去磁盘取数据,这段时间并不需要CPU,所以可以创建更多的线程去处理请求。
参考
《高并发系统设计 40 问》