Excutors 与 ThreadPoolExcutor 的关系与区别

先说结论。
线程池的创建分为两种:

  • Executors
  • ThreadPoolExecutor

Executors 是一个线程池的工具类,而 ThreadPoolExecutorExecutors 的具体实现。ThreadPoolExecutorExecutor 接口的一个实现,是线程池的核心类。Executors 工具类提供了很多方法来创建不同类型的线程池,比如 newFixedThreadPool(创建固定线程数的线程池)、newCachedThreadPool(创建缓冲线程池)、newSingleThreadPool(创建只有一个线程的线程池)等,但内部都是通过构造 ThreadPoolExecutor 的不同参数实例来构造线程池的。
所以 Executors 适用于想快速创建一个线程池而不在意内部实现的场景,而 ThreadPoolExecutor 更为灵活可控,可自定义创建拥有特定配置的线程池。
说完的结论再来详细说说 ExecutorsThreadPoolExecutor

Executors

Executors 创建线程池的方式有以下几种:

  • Executors.newFixedThreadPool:创建固定大小的线程池
  • Executors.newWorkStealingPool:创建抢占式线程池
  • Executors.newSingleThreadExecutor:创建单个线程的线程池
  • Executors.newCachedThreadPool:创建可缓存的线程池
  • Executors.newSingleThreadScheduledExecutor:创建单线程可执行延迟任务的线程池
  • Executros.newScheduledThreadPool:创建可执行延迟任务的线程池

可以看下源码:

public class Executors {
    /**
     * 创建可重用的固定数量的线程池。如果所有线程都处在活动状态,提交额外任务
     * 的时候,超出的线程在队列中等待。队列类型是 LinkedBlockingQueue
     * nThreads 为创建线程池的数量
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    /**
     * Java 8 新增的线程池,具有抢占式操作的线程池,每个线程都有一个任务队列存放任务,
     * 当线程发现自己的队列没有任务了,也就是先工作完了的线程就去帮助没处理完的线程工作。
     * 以实现最快完成工作。
     * 是基于 ForkJoinPool 创建的线程池,parallelism 参数自定义并行度。
     */
    public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

    /**
     * 同上,但是并行度是根据获取当前系统的 CPU 核心数来判断。
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

    /**
     * 创建固定数量线程的线程池,可控制线程最大并发数,超出的线程会在队列中等待。
     * 多了一个 ThreadFactory 参数,线程工厂,主要用来创建线程池
     */
    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

    /**
     * 创建单个线程的线程池。它可以保证先进先出的执行顺序。
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

    /**
     * 同上。
     */
    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }

    /**
     * 创建一个可缓存的线程池。适用于短期执行的异步任务,从代码中可以看出线程数的设定是
     * Integer.MAX_VALUE,不对线程池的大小做设定,可以创建无限数量的线程。
     * 但也就不适合执行长时间运行的任务,可能会导致系统资源耗尽。
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

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

    /**
     * 创建一个单线程的可以执行延迟任务的线程池,可以安排以给定延迟后执行的命令或定时执行的命令。
     * 
     */
    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

    /**
     * 同上
     */
    public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1, threadFactory));
    }

    /**
     * 创建一个可以执行延迟任务的线程池,任务数量自定义
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    /**
     * 同上
     */
    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
}

可以看到其实 Executors 创建的线程大部分都是由 ThreadPoolExecutor 实现。

ThreadPoolExecutor

直接看下他的构造函数:

public ThreadPoolExecutor(int corePoolSize, // 核心线程数,线程池中始终存活的线程数
                           // 最大线程数,线程池中允许的最大线程数
                          int maximumPoolSize,
                          // 最大线程数可以存活的时间
                          long keepAliveTime, 
                          // 时间单位
                          TimeUnit unit, 
                          // 阻塞队列,workQueue 包含七种
                          BlockingQueue<Runnable> workQueue, 
                           // 线程工厂,主要用来创建线程
                          ThreadFactory threadFactory,
                          // 拒绝策略
                          RejectedExecutionHandler handler ) {
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    this.prestartAllCoreThreads();
}

ThreadPoolExecutor 的执行原理如图:

posted @ 2024-03-22 13:04  knqiufan  阅读(197)  评论(0编辑  收藏  举报