44 使用Executors工具类创建不同的ThreadPoolExecutor
Diego38 50 1

1. 前言

从本节之前已经将线程池最核心的部分讲完,接下来是线程池内非重点章节,本节要介绍一个工具类Executors,它可以很方便的帮助你创建各种线程池。

在学习过程中,重点是要看每个方法背后的执行过程,已经创建不同类型线程池的特点。

2. Executos工具类

Executors是一个辅助工具类,通过它可以创建不同类型的ThreadPoolExecutor。 image

主要有一些几种,我们分别介绍

  • newFixedThreadPool 创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小,线程池的核心线程数等于最大线程池数。里面使用了linkedBlcokingQueue()无界队列,不会触发线程池的缩容,使用较为广泛。

  • newSingleThreadExecutor 创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。由于里面使用了linkedBlcokingQueue()无界,所以不会触发缩减线程池大小,里面的核心线程数和最大线程数量都等于1。

以上两种队列都是由可能触发OOM的,因为使用了无界队列。

  • newCachedThreadPool 创建一个可以无限大线程数的线程池,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系能够创建的最大线程大小,使用synchrousQueue队列,由于synchrousQueue队列队列不存储元素,实际上每次任务进来,都会自动创建线程,好在超过60秒,会自动回收空闲的线程。

以上队列也会有可能触发OOM,不是因为队列容量,而是因为线程数会无限增加。

  • newScheduledThreadPool 创建一个大小无限的定时任务线程池,此线程池支持定时以及周期性执行任务的需求。

代码样例如下:

public class ExecutorsTest {

    public static void main(String[] args) {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        cachedThreadPool.submit(() -> System.out.println("1"));
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
        fixedThreadPool.submit(() -> System.out.println("2"));
        ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutor.submit(() -> System.out.println("3"));
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        scheduledExecutorService.submit(() -> System.out.println(4));
    }
}

从代码上看,Executors来创建线程池比new ThreadPoolExecutor方便高效多了。

3. 总结

但是目前很多大厂,都已经不建议再使用Executors了,这是因为Executors不指定队列长度,设置不指定线程池中线程数量,很容易造成OOM。

在这里建议大家日常工作还是使用new ThreadPoolExecutor来创建线程池,而对于平时的测试,可以随意使用Executors,来快速创建ThreadPoolExecutor。

预览图
评论区

索引目录