目录
1、概述
数据库连接池 每次与数据链接,创建连接对象connection ,操作完之后进行销毁,频繁创建销毁比较耗时,创建一个池子,预先在池子中初始化好一部分连接Connection对象,使用时直接获取即可,用完还回,不需要频繁创建销毁。
( 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。)
2、为什么要使用线程池?
- 并发量大的情况下,频发创建销毁线程开销比较大,创建线程池缓解压力。
3、 ThreadPoolExecutor类
jdk5之后,提供ThreadPoolExecutor类来实现线程池创建,是建议被使用的,里面有7个参数来设置对线程池的特征的定义。
ThreadPoolExecutor继承了AbstractExecutorService类,并提供了四个构造器,事实上,通过观察每个构造器的源码具体实现,前三个都是调用第四个构造器进行初始化工作。
4、构造器中各个参数含义
- corePoolSize:核心线程池数量:在创建后核心线程池数量默认为0,有任务来了后,才会去创建线程去执行。或者调用了prestartAllCoreThreads()或者 prestartCoreThread()方法,进行预创建。
- maximumPoolSize:线程池总数量,表示线程池最大能装多少个线程。
- keepAliveTime:指的是非核心线程池中的线程,在没有任务执行时空闲多长时间后内销毁。
- unit: keepAliveTime 的时间单位
- workQueue:等待队列,可以自己来指定等待队列的实现类。
- threadFactory:线程工厂,主要用来创建线程;
- handler:表示当拒绝处理任务时的拒绝策略
5、线程池的执行
创建完成 ThreadPoolExecutor 之后,当向线程池提交任务时,通常使用 execute 方法。
execute 方法的执行流程图如下:
- 当有任务提交到线程池时,首先检测核心线程池是否已满:
- 未满:在核心线程池创建一个线程处理
- 已满:将任务添加到一个等待队列中
- 继续有任务提交过来,核心线程池已满,等待队列已满,这时就要创建非核心线程来处理任务,如果任务继续增多,核心线程池,等待队列,非核心线程池都已满,那么使用相应的拒绝策略处理。
6、线程池中的队列
- ArrayBlockingQueue:有界队列,是一个用数组实现的有界阻塞队列,按 FIFO排序量。
- LinkedBlockingQueue:可设置容量队列,基于链表结构的阻塞队列,按 FIFO排序任务,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度Integer.MAX_VALUE,吞吐量通常要高于 ArrayBlockingQuene;
7、线程池的拒绝策略
- CallerRunsPolicy:让提交任务的线程去执行,例如main线程
- AbortPolicy:抛出异常,阻止系统正常工作。
- DiscardOleddestPolicy:该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。
- DiscardPolicy:该策略丢弃无法处理的任务,不予任何处理。
8、execute 与 submit 的区别
- execute 适用于不需要关注返回值的场景
- submit 方法适用于需要关注返回值的场景
9、关闭线程池
关闭线程池可以调用 shutdownNow 和 shutdown 两个方法来实现。
- shutdownNow :立即终止线程任务
- shutdown:不接收新的任务,执行完任务关闭
10、创建线程4种方法
继承Thread类 ;实现Runable接口;实现Callable接口;用ThreadPoolExecutor类创建线程池