java多线程:阿里巴巴java开发手册为什么要禁用 Executors 创建线程池

背景

在上篇文章中java多线程:线程池的深度理解中,我们利用继承ThreadPoolExecutor类完成了线程池的创建。在JDK1.5以后增加了Executors类,该类提供了几种创建线程池的静态方法,比如:
在这里插入图片描述
但我们翻阅阿里java开发手册:文中醒目的用红字标明禁示用Executors创建以下四种类型的线程池。本文将通过对这些类型的线程池进行源码跟踪,逐个解析。
在这里插入图片描述

FixedThreadPool

FixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待,适用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景,它适用于负载比较重的服务器。
跟踪下源码:

  1. 在静态方法newFixedThreadPool中new 了一个LinkedBlockingQueue对象,
  2. 而这个LinkedBlockingQueue类的构造函中通过Integer.MAX_VALUE对队列的容量做了无界值的设置
/**
*Executors.java
*/
 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
...
/**
*LinkedBlockingQueue.java
*/
	/**
     * Creates a {@code LinkedBlockingQueue} with a capacity of
     * {@link Integer#MAX_VALUE}.
     */
    public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }
    /**
     * Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity.
     *
     * @param capacity the capacity of this queue
     * @throws IllegalArgumentException if {@code capacity} is not greater
     *         than zero
     */
    public LinkedBlockingQueue(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        last = head = new Node<E>(null);
    }

如果队列为无界,也即存储任务的队列中任务会堆积,直至系统OutOfMemeryError。
在这里插入图片描述

SingleThreadPool

SingleThreadPool是一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
看下SingleThreadPool的源码:与newFixedThreadPool一样,同样是new 了一个LinkedBlockingQueue对象,通过Integer.MAX_VALUE对队列的容量做了无界值的设置。

/**
*Executors.java
*/
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
 ...
 /**
*LinkedBlockingQueue.java
*/
	/**
     * Creates a {@code LinkedBlockingQueue} with a capacity of
     * {@link Integer#MAX_VALUE}.
     */
    public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

CachedThreadPool

我们两看CachedThreadPool:CachedThreadPool是大小无界的线程池,适用于执行很多的短期异步任务的小程序,或者是负载较轻的服务器。
源码如下:
-在newCachedThreadPool静态方法中通过new ThreadPoolExecutor对象,并将线程池的最大线程数通过Integer.MAX_VALUE设置为无界值。

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

线程池会不断地创建线程执行任务,直到系统报OutOfMemoryError。
在这里插入图片描述

ScheduledThreadPool

ScheduledThreadPool是一个定长线程池,支持定时及周期性任务执行。

-通过ScheduledThreadPoolExecutor构造函数将线程最大数目通过Integer.MAX_VALUE设为无界值
同CachedThreadPool 线程池一样,也有可能为导致系统OutOfMemoryError。

/**
*Executors.java
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
....
/**
*ScheduledThreadPoolExecutor.java
*/
public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

总结

java新手应该尽量采用ThreadPoolExecutor手工创建线程池,这样处理的方式可以更深入地了解线程池的运行规则。

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) 
序号 名称 类型 备注
1 corePoolSize int 线程池的基本大小
2 maximumPoolSize int 最大线程池大小
3 keepAliveTime long 线程最大空闲时间
4 unit TimeUnit 时间单位
5 workQueue BlockingQueue 线程等待队列
6 threadFactory ThreadFactory 线程创建工厂
7 handler RejectedExecutionHandler 拒绝策略
原创文章 56 获赞 8 访问量 4717

猜你喜欢

转载自blog.csdn.net/jpgzhu/article/details/106014784