利用ThreadPoolExecutor控制并发任务数量

此前在项目中有如下场景:可同时开启多个任务,但要控制同时并发的任务数。

这种场景刚好可借用ThreadPoolExecutor阻塞队列线程池来实现,先来看看其构造函数:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
  1. corePoolSize 线程池中持有的最小线程数
  2. maximumPoolSize 线程池中允许持有的最大线程数
  3. keepAliveTime 当线程数大于corePoolSize时,空闲线程被回收前最大存活时间
  4. unit 空闲线程被回收前最大存活时间的时间单位
  5. workQueue 请求任务运行前的缓冲队列
  6. threadFactory 线程工厂
  7. handler 线程池对拒绝任务的处理策略

当线程加入时:
1. 如果请求任务数小于corePoolSize则线程立即执行请求任务
2. 如果线程池中的线程数已达corePoolSize,则请求任务加入workQueue等待
3. 如果workQueue已满,且线程池中的总线程数未超过maximumPoolSize,则新建线程执行请求任务
4. 如果线程池中的线程数已达maximumPoolSize,则新来的任务按照handler 的策略进行处理。

考虑如下场景(任务运行时间假设无限长):
总任务数: 7
corePoolSize: 2
maximumPoolSize: 4
workQueue: 2

  1. 总线程数小于corePoolSize:首先任务1和任务2将立即投入运行;此时线程数为2
  2. 线程数已达corePoolSize:任务3和任务4将进入workQueue等待
  3. workQueue已满且线程池中的总线程数为2未超过maximumPoolSize:新建线程运行任务5和任务6;此时线程数为4
  4. 线程数已达maximumPoolSize:任务7将按照handler策略被拒绝

基于ThreadPoolExecutor创建的几个常用线程池:

  1. newFixedThreadPool

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

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

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

你可能感兴趣的:(java)