由于blog各种垃圾评论太多,而且本人审核评论周期较长,所以懒得管理评论了,就把评论功能关闭,有问题可以直接qq骚扰我

ThreadPoolExecutor创建线程池

JAVA 西门飞冰 49℃
[隐藏]

1.介绍

在java.util.concurrent中,提供了工具类Executors(调度器)对象来创建线程池,可创建的线程池有四种:

1、CachedThreadPool:可缓存线程池,如果数据请求过多,它会不断创建新的线程,并且它还可以灵活回收空闲的线程

2、FixedThreadPool:固定长度线程池,可以控制线程最大并发数,超出的线程会放到队列中

3、SingleThreadExecutor:单线程线程池,它只会用唯一的线程来执行任务

4、ScheduledThreadPool :用于定时执行任务线程池

但在阿里巴巴JAVA开发手册中,第三条明确说了只要创建线程就要使用线程池,但是在第四条中又明确说明不允许使用Java内置线程池Executors去创建,而是使用ThreadPoolExecutor创建线程池。

image-20221119191716779

要是IDEA导入阿里规约插件之后,使用Executor创建线程池,还会有红线提醒。

image-20221119192404716

文章下面内容就来看一下,阿里巴巴建议的通过ThreadPoolExecutor创建线程池方式如何操作。

2.JUC线程池实现原理

通过看JUC几个内置线程池的源码可以得出结论,这几个线程池除了调度线程池,底层都是new ThreadPoolExecutor实现的。

而且调度线程池在项目开发中也用不到,都是使用调度框架实现。

image-20221119192642426

image-20221119192725000

3.线程池7个参数

image-20221119193533621

常用的只有3个∶corePoolSizemaximumPoolSizeworkQueue。

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创建线程池

喜欢 (1)or分享 (0)