ThreadPoolExecutor笔记

58 篇文章 0 订阅
3 篇文章 0 订阅

线程池

主要控制运行线程的数量,将待处理的任务放入等待队列,创建线程执行任务,若超过最大线程池大小,等待其他任务执行完毕,再从队列中取出执行。

线程复用,控制最大并发数

线程池按以下行为执行任务

  1. 当线程数小于核心线程数时,创建线程。
  2. 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
  3. 当线程数大于等于核心线程数,且任务队列已满
    1. 若线程数小于最大线程数,创建线程
    2. 若线程数等于最大线程数,抛出异常,拒绝任务

 

工具类ExecutorsAPI创建方式

1、newFixedThreadPool,

    创建固定大小的线程池,超过最大任务数后会在等待队列等待

    等待队列为LinkedBlockingQueue,默认大小最大为Integer最大(OOM)

2 、newSingleThreadExecutor

   相当于newFix(1),问题也是队列大小最大Integer(OOM)

3、newCachedThreadPool

   可缓存线程池,线程数不足时创建新线程,超过时回收旧线程。线程最大数量无限制(导致OOM), 因为可复用,所以可以减少系统开销,工作队列为SynchronousQueue

 

阿里巴巴Java开发手册》的提示不容忽略:

【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样

的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors 返回的线程池对象的弊端如下:
1)FixedThreadPool 和 SingleThreadPool:

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

2)CachedThreadPool 和 ScheduledThreadPool:

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

 

 

正式编码中,推荐根据实际情况,使用new ThreadPoolExecutor来创建线程池

/**

* 使用给定的参数创建ThreadPoolExecutor.

*

* @param corePoolSize 核心线程池中的最大线程数

* @param maximumPoolSize 总线程池中的最大线程数 需大于等于1

* @param keepAliveTime 空闲线程的存活时间

* @param unit keepAliveTime的单位

* @param workQueue 任务队列, 保存已经提交但尚未被执行的线程

* @param threadFactory 线程创建工厂

* @param handler 拒绝策略 (当任务太多导致工作队列满时的处理策略)

*/

new ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

 

RejectedExecutionHandler 拒绝策略四种

在池中线程到达最大数量后,且任务队列也满了,则会调用RejectedExecutionHandler对新任务进行处理。

1、new ThreadPoolExecutor.AbortPolicy(); 为默认策略

直接抛出异常。源码如下

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

            throw new RejectedExecutionException();

        }

2、new ThreadPoolExecutor.CallerRunsPolicy();

在当前调用execute(Runnable r)的线程中直接调用run方法,异步改同步,由调用者线程处理。源码如下

       public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

            if (!e.isShutdown()) {

                r.run();

            }

        }

3、new ThreadPoolExecutor.DiscardOldestPolicy();

丢弃最早进入队列的任务,队列中加入新任务,源码如下

       public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

            if (!e.isShutdown()) {

                e.getQueue().poll();

                e.execute(r);

            }

        }

 

4、new ThreadPoolExecutor.DiscardPolicy();

直接丢弃新任务,不处理,源码如下

       public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

        }

 

生产中如何设置线程池各个参数?

我实际中用到线程池但是并发量不多,一分钟来3-5个任务,每个任务正常执行近10秒,设置了核4 最大8,考虑中间执行可能接口超时,超过10s,队列设置了15的参数

看了看别的博客,说的公式什么的,我理解不深,感觉一丝丝不得劲,先不写了,再研究研究

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值