目录
一、用连接池预先建立数据库连接
频繁创建数据库连接会造成响应时间变慢,只要使用连接池将数据库连接预先建立好,这样在使用的时候就不需要频繁地创建连接了,查询性能大大提升了。
数据库连接池有两个最重要的配置:最小连接数和最大连接数, 它们控制着从连接池中获取连接的流程
- 如果当前连接数小于最小连接数,则创建新的连接处理数据库请求;
- 如果连接池中有空闲连接则复用空闲连接;
- 如果空闲池中没有连接并且当前连接数小于最大连接数,则创建新的连接处理请求;
- 如果当前连接数已经大于等于最大连接数,则按照配置中设定的时间(C3P0的连接池配置是checkoutTimeout)等待旧的连接可用;
- 如果等待超过了这个设定时间则向用户抛出错误。
二、用线程池预先创建线程
JDK 1.5中引入的ThreadPoolExecutor就是一种线程池的实现,它有两个重要的参数:coreThreadCount和maxThreadCount,这两个参数控制着线程池的执行过程。
- 如果线程池中的线程数少于coreThreadCount时,处理新的任务时会创建新的线程;
- 如果线程数大于coreThreadCount则把任务丢到一个队列里面,由当前空闲的线程执行;
- 当队列中的任务堆积满了的时候,则继续创建线程,直到达到maxThreadCount;
- 当线程数达到maxTheadCount时还有新的任务提交,那么我们就不得不将它们丢弃了。
需要注意的几点:
- 我们平时开发的Web系统通常都有大量的IO操作,比方说查询数据库、查询缓存等等。任务在执行IO操作的时候CPU就空闲了下来,这时如果增加执行任务的线程数而不是把任务暂存在队列中,就可以在单位时间内执行更多的任务,大大提高了任务执行的吞吐量。Tomcat使用的线程池就不是JDK原生的线程池,而是做了一些改造,当线程数超过coreThreadCount之后会优先创建线程,直到线程数到达maxThreadCount,这样就比较适合于Web系统大量IO操作的场景了
- 线程池中使用的队列的堆积量也是我们需要监控的重要指标,对于实时性要求比较高的任务来说,这个指标尤为关键
- 使用线程池请一定记住不要使用无界队列,大量的任务堆积会占用大量的内存空间,一旦内存空间被占满就会频繁地触发Full GC,造成服务不可用