关于Executors类创建线程池newFixedThreadPool,newCachedThreadPool,newSingleThreadExecutor,newScheduledThr区别,使用

最近项目中使用到了线程池,习惯使用newCachedThreadPool创建,但是一直不是很明确Executors类下四种创建线程池的区别,经走访学习后,总结一下。


**注意:以下内容中 Integer.MAX_VALUE描述为无限大方便观看**

1. newFixedThreadPool(int cnt)

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

此方法是创建一个固定核心数线程池,以及LinkedBlockingQueue队列,其大小为无限大
也就说如果创建该线程池时,指定参数为10,那么就会在池中创建10个核心线程,以及一个无限大的LinkedBlockingQueue。
最大同时执行数为10,等待数无限大



2. newCachedThreadPool

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

此方法是创建了一个核心线程数为0,但是临时线程无限大(60秒)的池,该等待队列类为SynchronousQueue,与其称为队列,不如叫一个,如果该中存在一个元素,那么插入该点的线程将被阻塞,直到上的元素被消费。看似无意义(其实本人理解也无意义…),实则为了工厂参数的一致性做出的类似于妥协?(求大神科普)



3. newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

此方法是创建了仅有一个核心线程的线程池,无临时线程数,使用无限大的LinkedBlockingQueue数组作为队列。
一个线程的线程池有什么意义呢?
其实我理解的此线程池的意义就是直接体现了线程的复用性,且配合无限大的队列,执行一些不那么重要且必须执行的特殊任务。(如果每次任务时间长,还使用这种池不就等于守护线程循环执行吗?)



4. 问题发现

极端条件下:
newFixedThreadPool 中创建无线大的队列
newCachedThreadPool 创建无限大的线程数
newSingleThreadExecutor 不说了

极端条件下,怎么办呢?


5. 自定义线程池

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                10, 20,
                60L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100));

解释:
参数一:10条核心线程
参数二:20最大线程数
参数三:临时线程存活时间 60
参数四:参数三的单位 秒
参数五:队列类(LinkedBlockingQueue)长度100



6. 执行线程优先级的研究

调度优先级:核心线程 > 队列 > 临时线程

也就说,execute执行线程时,首先查看核心线程有无空闲线程,如果有则addWorker,如果没有,则加入队列,队列满则加入临时线程。

执行优先级:核心线程 > 临时线程 > 队列 

7. newScheduledThreadPool(int cnt)定时任务线程池

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

参数为核心线程数,临时线程无限大,并且临时线程结束后立刻销毁,
用DelayedWorkQueue作为队列类(因定时任务部分需要延时特殊性,需要此特殊的优先级队列,根据延时时间优先执行任务)




研究结束。如有理解错误的地方,请大神指导教育谢谢。

<think>嗯,用户问的是使用Executors创建线程池直接使用ThreadPoolExecutor区别。首先,我得回想一下Java线程池的相关知识。记得Executors工具提供了很多静态方法来创建不同型的线程池,比如newFixedThreadPoolnewCachedThreadPool这些。而ThreadPoolExecutor则是更底层的,允许更详细的参数配置。 那用户可能想知道这两种方式在使用上的区别,或者为什么有时候推荐用ThreadPoolExecutor而不是Executors。可能涉及到参数配置的灵活性问题,或者Executors某些方法可能隐藏了一些潜在的问题,比如资源耗尽的风险。比如newCachedThreadPool可能会创建多线程,而newFixedThreadPool使用的无界队列可能导致OOM。 接下来需要整理两者的区别,包括参数控制、资源管理、以及最佳实践。比如Executors的方法可能隐藏了具体的参数设置,而直接使用ThreadPoolExecutor可以让开发者明确指定核心线程数、最大线程数、队列型等,从而避免资源问题。另外阿里巴巴的开发手册好像提到过不建议使用Executors,而推荐ThreadPoolExecutor,这点也应该提到。 还要给出代码示例,比如用Executors创建ThreadPoolExecutor直接创建的对比。然后解释每个参数的意义,比如corePoolSize、maximumPoolSize、keepAliveTime、workQueue,以及RejectedExecutionHandler的作用。 然后,在相关问题部分,需要设计几个相关问题,比如线程池参数的意义、四种线程池区别、无界队列的问题,以及拒绝策略的型。这些都能帮助用户更深入理解线程池的配置潜在问题。</think><< 使用`Executors`工具创建线程池直接使用`ThreadPoolExecutor`的区别主要体现在对线程池参数的透明性资源控制能力上。以下是具体区别示例: ### 1. **参数控制与默认行为** - **Executors**: - 提供预定义的线程池型(如`newFixedThreadPool`, `newCachedThreadPool`等),但隐藏了底层参数细节。 - 某些方法可能使用默认的无界队列(如`LinkedBlockingQueue`),可能导致内存溢出(OOM)。 ```java // 使用Executors创建固定线程池(无界队列) ExecutorService executor = Executors.newFixedThreadPool(10); ``` - `newCachedThreadPool`默认使用`SynchronousQueue`,允许无限线程增长(最大为`Integer.MAX_VALUE`),可能耗尽系统资源。 - **ThreadPoolExecutor**: - 需要手动指定核心参数(核心线程数、最大线程数、队列型、拒绝策略等),对资源控制更透明。 ```java // 手动创建ThreadPoolExecutor(有界队列 + 明确拒绝策略) ThreadPoolExecutor executor = new ThreadPoolExecutor( 5, // 核心线程数 10, // 最大线程数 60L, TimeUnit.SECONDS, // 空闲线程存活时间 new ArrayBlockingQueue<>(100), // 有界队列(容量100) new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 ); ``` ### 2. **资源管理风险** - **Executors**的`newFixedThreadPool``newSingleThreadExecutor`使用无界队列(默认`Integer.MAX_VALUE`),任务堆积时可能触发OOM。 - **ThreadPoolExecutor**通过有界队列(如`ArrayBlockingQueue`)自定义拒绝策略(如`AbortPolicy`),可主动避免资源耗尽。 ### 3. **最佳实践** - 阿里巴巴《Java开发手册》明确禁止使用`Executors`创建线程池,推荐直接使用`ThreadPoolExecutor`,以明确线程池行为。 ### 示例对比 ```java // 不安全的Executors方式(无界队列) ExecutorService unsafeExecutor = Executors.newFixedThreadPool(10); // 安全的ThreadPoolExecutor方式(有界队列 + 拒绝策略) ExecutorService safeExecutor = new ThreadPoolExecutor( 5, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.AbortPolicy() ); ``` ### 核心区别总结 | 特性 | Executors | ThreadPoolExecutor | |---------------------|-------------------------------|-------------------------------| | **参数透明度** | 隐藏底层参数 | 完全透明,需手动指定所有参数 | | **队列型** | 可能使用无界队列(如`LinkedBlockingQueue`) | 可灵活选择有界/无界队列 | | **资源控制** | 默认配置易引发OOM | 显式控制队列线程数量 | | **拒绝策略** | 默认`AbortPolicy` | 可自定义(如`CallerRunsPolicy`) |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值