java中Executors创建线程池的三种方法

本文详细对比了三种线程池的创建方式:单线程、固定大小和可伸缩线程池,分析了它们的特性及适用场景。并通过源码解读了ThreadPoolExecutor构造方法,强调了避免使用Executors创建线程池的重要性。

三个关键线程池的比较

1、创建单个线程(单例模式)
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

由于调用的ThreadPoolExecutor的构造方法的核心池大小和最大线程池均为1,所以该线程池只能存在一个线程。

2、创建固定大小的线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

我们可以看到,该创建线程池的方法提供了一个课传递的参数nThreads,该参数可以设置线程池的核心大小以及最大容量,即该线程池的固定大小。

3、可以伸缩的线程池
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

我们可以看到,这里的最大线程大小可以达到Integer的最大大小2147483647,一般情况下我们是用不了这么多线程的,想用这么多的线程,是需要强大的硬件设备的支持,我们可以看到在线程被创建后60s如果没有被调用就会被释放,关于这些参数我会在后面讲到。

这几种方式创建的线程池都是通过创建ThreadPoolExecutor对象来实现的

4、ThreadPoolExecutor

我们来看一下这三个线程池创建时调用的ThreadPoolExecutor的构造方法

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

我们看下这里面调用的this方法

public ThreadPoolExecutor(int corePoolSize,	// 核心线程池大小
                          int maximumPoolSize,	// 最大线程池大小
                          long keepAliveTime,	// 超时了没有人调用就会释放
                          TimeUnit unit,	// 超时单位
                          BlockingQueue<Runnable> workQueue,	// 阻塞队列
                          ThreadFactory threadFactory,	// 线程工厂,创建线程线程的
                          RejectedExecutionHandler handler) {// 拒绝策略
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.acc = System.getSecurityManager() == null ?
        null :
    AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

所以我们看到这些方法本质上都是调用了ThreadPoolExecutor的构造方法

注意:虽然用Executors创建线程池可以方便我们的操作,但是阿里发布的 Java开发手册中强制线程池不允许使用 Executors 去创建,所以建议大家还是用ThreadPoolExecutor 来创建线程池

ThreadPoolExecutor创建线程池参考https://blog.youkuaiyun.com/jjj___jjj/article/details/105314542

Java 的 `Executors` 工具类提供了多种创建线程池的静态工厂方法,用于简化 `ThreadPoolExecutor` 的配置。以下是常用的方法及其特点: --- ### **1. 固定大小线程池 (`newFixedThreadPool`)** ```java ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads); ``` - **特点**: - 线程池中保持固定数量的核心线程(`nThreads`),即使线程空闲也不会被回收。 - 任务队列使用无界的 `LinkedBlockingQueue`,可能导致内存溢出(OOM)。 - **适用场景**: 适合已知并发量且需要严格控制线程数的任务(如服务器请求处理)。 --- ### **2. 单线程池 (`newSingleThreadExecutor`)** ```java ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(); ``` - **特点**: - 只有一个线程按顺序执行任务。 - 同样使用无界队列,存在 OOM 风险。 - **适用场景**: 需要保证任务顺序执行的场景(如日志写入、异步事件队列)。 --- ### **3. 可缓存线程池 (`newCachedThreadPool`)** ```java ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); ``` - **特点**: - 线程数量根据任务动态增减(空闲线程默认 60 秒回收)。 - 任务队列使用 `SynchronousQueue`(直接移交任务,不存储)。 - 可能创建大量线程导致资源耗尽。 - **适用场景**: 短生命周期的异步任务(如 HTTP 请求响应)。 --- ### **4. 定时任务线程池 (`newScheduledThreadPool`)** ```java ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize); ``` - **特点**: - 支持定时或周期性任务(如 `scheduleAtFixedRate`)。 - 核心线程数固定,但非核心线程可无限创建(依赖任务频率)。 - **适用场景**: 定时任务(如心跳检测、数据同步)。 --- ### **5. 工作窃取线程池 (`newWorkStealingPool`)(Java 8+)** ```java ExecutorService workStealingPool = Executors.newWorkStealingPool(int parallelism); ``` - **特点**: - 基于 ForkJoinPool 实现,使用工作窃取(Work-Stealing)算法提高并行效率。 - 默认并行度为 CPU 核心数。 - **适用场景**: 计算密集型任务(如分治算法、并行流处理)。 --- ### **注意事项** 1. **无界队列风险**: `FixedThreadPool` 和 `SingleThreadPool` 使用无界队列,任务堆积可能导致 OOM。 2. **资源耗尽风险**: `CachedThreadPool` 可能创建多线程,需谨慎使用。 3. **推荐替代方案**: 直接使用 `ThreadPoolExecutor` 构造函数,明确指定队列类型和拒绝策略。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值