為什么不推薦使用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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM