为什么建议不要使用Executors来创建线程池?

简介: 为什么建议不要使用Executors来创建线程池?

b9a96665cdd247868d2b20917445862a.png

阿里作为国内Java使用最多的大厂,他出版了一部《阿里巴巴Java开发手册》,不知道大家看过没,没有看过的话,建议大家看看。


对于我们编程养成良好的习惯还是很有帮助的,最近我在看到并发这一规约的时候,他们就明确了一点:线程池不允许使用 Executors来创建。


在多线程编程中,线程池是一种重要的资源管理工具,用于提高程序效率和降低资源消耗。


Java通过java.util.concurrent包提供了丰富的线程池管理工具,其中Executors类是创建线程池的常用工具。


然而,像阿里巴巴这样的大型技术公司却建议开发者避免使用Executors来创建线程池。为什么会有这样的建议呢?


1、文档出处


84946b4d4827ffcbb3941d234f1b31b3_ced88ee2b20a016be2bacae6c6451cd2.png


2、Executors类的问题

Executors类提供了几种快捷方法来创建不同类型的线程池,例如newFixedThreadPool、newCachedThreadPool和newSingleThreadExecutor等。这些方法虽然使用方便,但存在以下几个问题:


1.1 默认线程工厂的局限性

Executors使用的默认线程工厂创建的线程都是非守护线程,且没有设置线程名称和优先级。这在某些应用场景中可能不是最佳选择。


1.2 无限制的任务队列

某些由Executors创建的线程池,如newCachedThreadPool,使用了无限制的任务队列。这意味着如果任务提交速度超过线程处理速度,会导致内存溢出风险。


1.3 缺乏灵活性和透明度

使用Executors快捷方法创建的线程池隐藏了许多重要的配置细节,比如线程数量和任务队列类型,这降低了配置的灵活性和透明度。


3、如何创建线程池呢?

鉴于上述问题,阿里巴巴在其Java开发手册中建议开发者不要使用Executors类的快捷方法创建线程池,


那么我们应该如何创建线程池呢?


答案就是使用:ThreadPoolExecutor。


我们可以看下这个类:

 


ThreadPoolExecutor构造函数允许开发者自定义线程池的多个参数,包括核心线程数、最大线程数、空闲线程存活时间、任务队列、线程工厂和拒绝策略等。这些自定义的配置可以更好地满足不同的应用需求。


所以,创建高效和可靠的线程池时应考虑以下几点:

  • 合理设置线程数量:线程池大小应根据系统资源和需求合理设置。
  • 选择适当的任务队列:根据任务类型和执行策略选择合适的队列类型。
  • 自定义线程工厂:可以设置更有意义的线程名称,方便问题追踪和调试。
  • 合理的拒绝策略:在任务队列满时选择合适的拒绝策略,如AbortPolicyCallerRunsPolicy等。


下面给出一段最佳实践代码供大家参考:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
 
public class ThreadPoolExample {
 
    public static void main(String[] args) {
        // 核心线程数
        int corePoolSize = 5;
        // 最大线程数
        int maximumPoolSize = 10;
        // 当线程数大于核心线程数时,多余空闲线程的存活时间
        long keepAliveTime = 5000;
        // 时间单位,这里使用毫秒
        TimeUnit unit = TimeUnit.MILLISECONDS;
 
        // 任务队列,使用有界队列可以避免资源耗尽的问题
        ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(100);
 
        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue
        );
 
        // 示例任务提交
        for (int i = 0; i < 20; i++) {
            int finalI = i;
            executor.execute(() -> {
                System.out.println("Executing task " + finalI + " using thread " + Thread.currentThread().getName());
                try {
                    // 模拟任务执行时间
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
 
        // 关闭线程池
        executor.shutdown();
    }
}


这段代码展示了如何使用 ThreadPoolExecutor 来创建一个自定义的线程池。以下是关键配置的说明:


  • corePoolSize(核心线程数):线程池保持活跃状态的线程数量,即使这些线程处于空闲状态。
  • maximumPoolSize(最大线程数):线程池能够容纳的最大线程数量。
  • keepAliveTime(线程存活时间):当线程数量超过核心线程数时,多余的空闲线程可以存活的时间。
  • unit(时间单位):用于 keepAliveTime 的时间单位。
  • workQueue(任务队列):存储待执行任务的队列。这里使用了 ArrayBlockingQueue 作为有界队列,以避免资源耗尽的风险。


创建线程池后,通过 execute 方法提交任务。最后,使用 shutdown 方法来关闭线程池,以释放资源。

相关文章
|
6月前
|
缓存 Java p3c
【Java用法】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
【Java用法】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
123 0
|
4月前
|
Java API 开发者
为什么禁止使用Executors创建线程池?
为什么禁止使用Executors创建线程池?
95 0
|
5月前
|
Java
Java 利用JUC CountDownLatch 线程池Executors 实现多线程操作
Java 利用JUC CountDownLatch 线程池Executors 实现多线程操作 业务场景:某个业务操作非常耗时,但又必须等这个操作结束后才能进行后续操作
49 0
ThreadPoolExecutor的中的submit和FutureTask || 通过Executors 创建线程池的一些实例(Callable和Runnable的在其中的体现)
ThreadPoolExecutor的中的submit和FutureTask || 通过Executors 创建线程池的一些实例(Callable和Runnable的在其中的体现)
123 0
|
Java 编译器 p3c
阿里巴巴:禁止使用 Executors 创建线程池!为什么啊?
阿里巴巴:禁止使用 Executors 创建线程池!为什么啊?
540 0
阿里巴巴:禁止使用 Executors 创建线程池!为什么啊?
|
Java 数据库
【小家Java】自定义的线程池需要关闭吗?(局部变量Executors线程池一定要手动关闭)
【小家Java】自定义的线程池需要关闭吗?(局部变量Executors线程池一定要手动关闭)
【小家Java】自定义的线程池需要关闭吗?(局部变量Executors线程池一定要手动关闭)
|
存储 缓存 网络协议
阿里巴巴为什么要禁用 Executors 创建线程池?
看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用 Executors 去创建,而是通过ThreadPoolExecutor的方式,通过源码分析禁用的原因。 写在前面
阿里巴巴为什么要禁用 Executors 创建线程池?
|
Web App开发 Java API