目录
6) ThreadFactory threadFactory
7)RejectedExecutionHandler handler
1.线程池的定义
线程池(ThreadPool)是一种多线程处理方式,它预先创建了一组线程并管理它们的生命周期,用于处理提交的任务。
2.创建线程池的背景
Java中使用多线程正是由于进程的频繁的创建和销毁的开销过大,所以才转而使用开销更小的线程。而随着科技的发展,线程的频繁的创建和销毁也逐渐所不能被Java接受。因而Java引入了线程池(ThreadPool)这一概念。
3.线程池的优点
1)降低资源消耗:有效地减少了线程创建和销毁所带来的开销
2)提高响应速度:任务到达时可以直接执行,无需等待线程创建(线程池创建时就已经创建了一组线程,以待使用)。
3)提高线程可管理性:统一分配、调优和监控线程
4)防止资源耗尽:通过限制最大线程数防止系统被过载
4.线程池的创建方法
(1)ThreadPoolExecutor
Java通过java.util.concurrent.ThreadPoolExecutor
提供线程池支持:
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 空闲线程存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 工作队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
1)corePoolSize
corePoolSize的含义是核心线程数。打个比方就是一个公司的正式员工的数量,正式员工一经录用,永不辞退。核心线程就好比是正式员工,在线程池的创建时就被创建出来,并且永不被销毁。
2)maximumPoolSize
maximumPoolSize的含义是最大线程数。最大线程数=核心线程数+非核心线程数。打个比方就是一个公司里面所有的正式员工数量+所有实习生数量。其中正式员工是核心线程数,实习生是非核心员工数量。
3) keepAliveTime
keepAliveTime的含义是空闲线程存活时间。也就是非核心线程可以空闲的最大时间。打个比方就是一个公司里面实习生可以摸鱼的最大时间,超过这个时间实习生还是没有活干,公司就会把实习生辞退。
4)TimeUnit unit
TimeUnit unit的含义是时间单位。它可以是秒,也可以是毫秒、纳秒等。
5)BlockingQueue<Runnable> workQueue
BlockingQueue<Runnable> workQueue的含义是工作队列。通过Execute方法提交的Runnable对象会存放在这个队列中。
6) ThreadFactory threadFactory
ThreadFactory threadFactory的含义是线程工厂。它是一个接口,基于工厂模式来创建的。
7)RejectedExecutionHandler handler
RejectedExecutionHandler handler的含义是拒绝策略,是当队列阻塞(任务量满了)的处理方式。它分为四种:AbortPolicy()、 CallerRunsPolicy()、 DiscardOldestPolicy()、DiscardPolicy()。
1.AbortPolicy()
AbortPolicy()的处理方式是线程池直接抛出异常。打个比方就是在公司里面一个员工的任务量溢出,他直接跟领导汇报:我的活太多了,干不了了,我心态崩了。这个时候领导批了他一天假取调整心态。这个时候,不但新添加的任务处理不了,原来的那些任务也处理不了。因为他心态崩了(抛出异常)。
2.CallerRunsPolicy()
CallerRunsPolicy()的的处理方式是让调用submit的线程自行执行任务。打个比方就是公司里面一个员工的任务量已经满了,这时,领导让他再去干一件事,员工就说:我时间满了,你自己干吧。然后领导就自己把这件事处理了。
3)DiscardOldestPolicy()
DiscardOldestPolicy()的处理方式是丢弃任务队列中最古老的任务。打个比方就是员工这时把最早派来的活丢弃了(不干了),这时空出来点时间,把这件新派来的活干了。
4)DiscardPolicy()
DiscardOldestPolicy()的处理方式是丢弃任务队列中最新的任务。打个比方就是员工说自己时间满了,这件新派来的活干不了(丢弃最新的任务)。
(2)Executors
// 1. 固定大小线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
// 2. 单线程池(保证任务顺序执行)
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
// 3. 可缓存线程池(自动扩容)
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// 4. 定时任务线程池
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
相对而言,使用Java中自带的创建线程池的方法就要简单很多,但是也带来了资源浪费(一下创建好多线程)的情况。