线程池的好处
频繁的创建和销毁线程会浪费大量的系统资源,增加并发编程的风险
,另外,在服务器负载过大时,如何让新的线程等待或者友好的拒绝服务,这些都是线程自身无法解决的,所以需要线程池来协调多个线程
线程池的作用:
- 利用线程池管理并复用线程、控制最大并发数等
- 实现任务线程队列缓存策略和拒绝机制
- 实现某些与时间相关的功能,如定时执行、周期执行等
- 隔离线程环境
为什么要使用线程池
- 降低资源消耗。 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。 当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- 提高线程的可管理性。 线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,
- 使用线程池可以进行统一的分配,调优和监控。
线程池是如何创建线程的
《阿里巴巴Java开发手册》中强制线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险
首先从从ThreadPoolExecutor(java.util.concurrent包下)构造方法讲起,先来看看参数最多的这个构造函数
代码语言:javascript复制public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
}
参数说明(共计7个参数):
- corePoolSize 表示池中所保存的线程数,包括空闲线程
- maximumPoolSize 表示线程池能够容纳同时执行的最大线程数
- keepAliveTime 表示线程池中的线程空闲时间
- unit 表示keepAliveTime 参数的时间单位
- workQueue 执行前用于保持任务的队列
- threadFactory 表示线程工厂它用来生产一组相同任务的结程
- handler 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序
可以看到启动程序时发现是进入了创建线程池的方法
通过断点可以看到创建线程池的类是TCPTransport
静态代码块:静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数
线程池类图
ThreadPoolExecutor提供的四个静态内部类
- AbortPolicy 丢弃任务并抛出异常
- DiscardPolicy 丢弃任务单不抛出异常,这是不推荐的做法
- DiscardOldestPolicy 抛弃队列中等待最久的任务
- CallerRunsPolicy 调用任务的run方法绕过线程池直接执行