1.介绍
在java.util.concurrent中,提供了工具类Executors(调度器)对象来创建线程池,可创建的线程池有四种:
1、CachedThreadPool:可缓存线程池,如果数据请求过多,它会不断创建新的线程,并且它还可以灵活回收空闲的线程
2、FixedThreadPool:固定长度线程池,可以控制线程最大并发数,超出的线程会放到队列中
3、SingleThreadExecutor:单线程线程池,它只会用唯一的线程来执行任务
4、ScheduledThreadPool :用于定时执行任务线程池
但在阿里巴巴JAVA开发手册中,第三条明确说了只要创建线程就要使用线程池,但是在第四条中又明确说明不允许使用Java内置线程池Executors去创建,而是使用ThreadPoolExecutor创建线程池。
2.JUC线程池实现原理
通过看JUC几个内置线程池的源码可以得出结论,这几个线程池除了调度线程池,底层都是new ThreadPoolExecutor实现的。
而且调度线程池在项目开发中也用不到,都是使用调度框架实现。
3.线程池7个参数
常用的只有3个∶corePoolSize、maximumPoolSize和 workQueue。
corePoolSize:一般设置为maximumPoolSize 的五分之一
maximumPoolSize:一般设置为CPU的核心数+1。
workQueue:队列积压长度,在满足业务的前提下做压测,尽量减少队列积压
4.线程拒绝策略
当提交任务数大于 corePoolSize 的时候,会优先将任务放到 workQueue 阻塞队列中。当阻塞队列饱和后,会扩充线程池中线程数,直到达到maximumPoolSize 最大线程数配置。此时,再多余的任务,则会触发线程池的拒绝策略了。
总结起来,也就是一句话,当提交的任务数大于(workQueue.size() + maximumPoolSize ),就会触发线程池的拒绝策略。
线程拒绝策略有如下五种:
1、AbortPolicy:丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行。
2、CallerRunsPolicy:这个拒绝策略就是谁调用了本线程池,则谁来执行任务,保证任务不会丢失。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大
3、DiscardPolicy: 直接丢弃,其他啥都没有
4、DiscardOldestPolicy:丢弃阻塞队列 workQueue 中最老的一个任务,并将新任务加入
5、实现RejectedExecutionHandler接口,可自定义处理器
5.
//自定义线程池创建 public class ThreadPoolDemo { public static void main(String[] args) { ExecutorService threadPool = new ThreadPoolExecutor( 1, 5, 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() ); //10个用户请求 try { for (int i = 1; i <=10; i++) { //执行 threadPool.execute(()->{ System.out.println(Thread.currentThread().getName()+"处理用户请求"); }); } }catch (Exception e) { e.printStackTrace(); }finally { //关闭 threadPool.shutdown(); } } }
转载请注明:西门飞冰的博客 » ThreadPoolExecutor创建线程池