写点什么

认识 ThreadPoolExecutor

作者:zarmnosaj
  • 2022 年 7 月 04 日
  • 本文字数:1353 字

    阅读完需:约 4 分钟

线程池的创建

我们一般不会使用 Executors 创建线程池,因为会有规避资源耗尽的风险。举例说明:


  1. FixedThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

  2. SingleThreadPool:和 FixedThreadPool 会面临同样的问题

  3. CachedThreadPool :允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

  4. ScheduledThreadPool:和 CachedThreadPool 会面临同样的问题


而 Executors 中方法 Executors.newFixedThreadPool()、Executors.newSingleThreadExecutor() 和 Executors.newCachedThreadPool(),底层都是通过 ThreadPoolExecutor 实现的。


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;}
复制代码


  1. corePoolSize 表示线程池的核心线程数。如果设置为 0,则在没有任何任务时会销毁线程池;如果大于 0,即使没有任务时也会保证线程池的线程数量等于此值。

  2. maximumPoolSize 表示线程池在任务增多时,可以创建的最大线程数。

  3. keepAliveTime 表示线程的存活时间,当线程池空闲时并且超过了此时间,多余的线程就会销毁,直到线程池中的线程数量销毁的等于 corePoolSize 为止,如果 maximumPoolSize 等于 corePoolSize,那么线程池在空闲的时候也不会销毁任何线程。

  4. unit 表示存活时间的单位

  5. workQueue 表示线程池执行的任务队列,当线程池的所有线程都在处理任务时,如果来了新任务就会缓存到此任务队列中排队等待执行。

  6. threadFactory 表示线程的创建工厂


注意:如果 corePoolSize 设置的比较小,则会频繁的创建和销毁线程,如果设置的比较大,则会浪费系统资源,所以需要根据实际业务来调整此值。

提交线程任务

提交线程任务的两种方式:


  1. submit()

  2. execute()


其中,submit() 方法可以配合 Futrue 来接收线程执行的返回值,属于 ExecutorService 接口的方法;execute()无返回值。

任务拒绝策略

  1. AbortPolicy,终止策略,线程池会抛出异常并终止执行,它是默认的拒绝策略;

  2. CallerRunsPolicy,把任务交给当前线程来执行;

  3. DiscardPolicy,忽略此任务(最新的任务);

  4. DiscardOldestPolicy,忽略最早的任务(最先加入队列的任务)。

  5. 自定义拒绝策略

发布于: 刚刚阅读数: 3
用户头像

zarmnosaj

关注

靡不有初,鲜克有终 2020.02.06 加入

成都后端混子

评论

发布
暂无评论
认识ThreadPoolExecutor_7月月更_zarmnosaj_InfoQ写作社区