为什么不推荐使用Executors来创建线程池

先来看看线程池的7大参数:

corePoolSize,maximumPoolSize,keepAliveTime,timeUnit,blockingQueue,threadFactory,rejectedExecutionHandler

常见的几个线程池

FixedThreadPool ==> 创建一个可重用固定线程数的线程池

CachedThreadPool ==> 创建一个可根据需要创建新线程的线程池

SingleThreadExexutor ==> 创建一个使用单个 worker 线程的 Executor

ScheduleThreadPool ==> 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

创建线程池的方式-使用Executors创建

Executors.newFixedThreadPool(int nThread)

 public static ExecutorService newFixedThreadPool(int nThreads) {
       return new ThreadPoolExecutor(nThreads, nThreads,
                                     0L, TimeUnit.MILLISECONDS,
                               new LinkedBlockingQueue<Runnable>());
 }

而我们来看看这个LinkedBlockingQueue:

public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
}

public LinkedBlockingQueue(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        last = head = new Node<E>(null);
}

很清晰的可以看到使用LinkedBlockingQueue创建的是Integer.MAX_VALUE大小的队列,会堆积大量的请求,从而造成OOM

Executors.newSingleThreadExexutor()

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
}

同样使用的阻塞队列是LinkedBlockingQueue,问题还是一样的

Executors.newCachedThreadPool()

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

可以看到,该线程池使用的最大线程数是Integer.MAX_VALUE,可能会创建大量线程,导致OOM的发生

Executors.newScheduleThreadPool()

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
}

可以看到 和上面是一样的问题,最大线程数是Integer.MAX_VALUE

在《阿里巴巴开发手册》中禁止了使用Executors来创建线程池, 而使用的是ThreadPoolExecutor构造函数来创建线程池:

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;
}
posted @ 2020-03-22 11:04  丁茜萌萌哒  阅读(868)  评论(0编辑  收藏  举报