为什么要使用线程池?什么是线程池?字面意思(他是一种基于池化思想管理和使用线程的机制,他将多个线程预先存储在一个池子中)
池化思想应用:
内存池:预先申请内存,提升申请内存速度,减少内存碎片.
连接池:预先申请数据库连接,提升连接速度,降低系统开销。
实例池:循环使用对象,减少资源在初始化和释放。比如字符串常量池
线程池的优势
1.降低系统资源消耗,通过重用已存在的线程,降低线程的创建和销毁造成的消耗
2.提高系统响应速度,当有任务到达时,无需等待线程的创建就能立即执行
3.方便线程并发数的管控,线程若是无限制创建,不仅会额外大量系统资源,还会引起阻塞。
4.线程池还提供了定时、定期以及可控线程数等功能的线程池,使用方便
线程池的创建主要分为两类:
1、Executors框架:但是阿里开发手册上不建议使用这种方式,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
- Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待;
- Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程;
- Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执行顺序;
- Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池;
- Executors.newSingleThreadScheduledExecutor:创建一个单线程的可以执行延迟任务的线程池;
- Executors.newWorkStealingPool:创建一个抢占式执行的线程池(任务执行顺序不确定)【JDK 1.8 添加】。
- ThreadPoolExecutor:最原始的创建线程池的方式,它包含了 7 个参数可供设置,后面会详细讲。
Executor返回线程池对象弊端如下:
- FixedThreadPool和SingleThreadExecutor:允许请求队列长度为Integer.MAX_VALUE,可能堆积大量请求,从而导致OOM
- CachedThreadPool和ScheduleThreadPool: 允许创建的线程数量为Integer.MAX_VALUE,可能会创建大量线程导致oom。
2、ThreadPoolExecutor构造方法:
ThreadPoolExcutor类提供的四个构造方法,我们来看最长的那个,其余三个都是在这个基础上产生的(其他几个构造方法说白点都是给定某些默认参数的构造方法比如默认制定拒绝策略是什么),这里就不贴代码讲了,比较简单。
[code]/**
* 用给定的初始参数创建一个新的ThreadPoolExecutor。
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize |