Java线程池

Java线程池

1. 线程池参数

1.1 参数说明

参数名描述
corePoolSize线程池核心线程数最大值
maximumPoolSize线程池最大线程数大小
keepAliveTime线程池中,非核心线程空闲的存活时间大小
unit线程空闲存活时间单位,即keepAliveTime的时间单位
workQueue存放任务的阻塞队列
threadFactory用于设置创建线程的工厂,可以给创建的线程设置有意义的名字,方便排查问题
handler线程池的饱和事件策略(拒绝策略),当任务队列满了且线程数已经超过maximumPoolSize,就会触发

线程池里的线程是在任务提交的时候创建:

  1. 当前运行线程数小于corePoolSize : 创建Worker对象,并指向Thread,保持引用以确保不会被GC回收
  2. 当前运行线程数大于等于corePoolSize:尝试任务入队等待(workQueue
    1. 入队成功:等待线程池的调度
    2. 入队失败:判断线程数是否已经超过maximumPoolSize
      1. 是:触发拒绝策略(handler
      2. 否:创建非核心线程处理任务

上述流程中创建出来的非核心线程,根据 keepAliveTime + unit 判断空闲一段时间之后,会被销毁,或者运行的任务抛出异常时也会被销毁

PS: 当task抛出异常后,线程池中的这个工作线程不会再执行其他task,但是会创建出新的线程来运行其他task

1.2 源码注释

线程池的类为 java.util.concurrent.ThreadPoolExecutor

    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

1.3 拒绝策略

线程池自带了四种拒绝策略,也可以通过实现 RejectedExecutionHandler 接口来自定义拒绝策略 。

  1. AbortPolicy:抛出一个RejectedExecutionException异常(默认的拒绝策略)
  2. CallerRunsPolicy:将执行的任务直接交给调用线程池的所在线程直接执行。比如调用execute方法的线程内
  3. DiscardPolicy:直接静默地丢弃,不会有任何通知。
  4. DiscardOldestPolicy:丢弃workQueue中最老的任务(即最早提交的任务),然后尝试重新执行当前任务。

1.4 阻塞队列

队列名说明使用场景
ArrayBlockingQueue有界阻塞队列,用数组实现
FIFO(先进先出)
初始化时需要指定容量大小
利用 ReentrantLock 实现线程安全
数据缓存
限流
生产-消费模式
LinkedBlockingQueue阻塞队列,用链表实现
是否有界取决于是否设置容量
默认容量为Integer.MAX_VALUE 一般视为无界队列
数据缓存
生产-消费模式
DelayQueue任务定时周期的延迟执行的无界队列
元素必须实现 Delayed 接口
延迟期满时才能从队列中提取元素
任务延迟执行
PriorityBlockingQueue具有优先级的无界阻塞队列
每次出队都返回优先级最高的元素
异步处理
任务调度
SynchronousQueue无缓冲的阻塞队列,不储存元素,入队和出队一起执行
不需要入队等待的场景,详见下面newCachedThreadPool 的应用
线程间通信
多任务非等待处理

2. 四种常用线程池介绍

四种常用线程池分别为:

  • newFixedThreadPool:固定数目线程的线程池
  • newCachedThreadPool:可缓存线程的线程池
  • newSingleThreadExecutor:单线程的线程池
  • newScheduledThreadPool:定时及周期执行的线程池

2.1 参数说明

四个线程池均支持自定义 threadFactory

拒绝策略默认为RejectedExecutionHandler defaultHandler = new AbortPolicy()

corePoolSizemaximumPoolSizekeepAliveTimeunitworkQueue
newFixedThreadPool自定义同corePoolSize0NANOSECONDSLinkedBlockingQueue
newCachedThreadPool0Integer.MAX_VALUE60SECONDSSynchronousQueue
newSingleThreadExecutor110MILLISECONDSLinkedBlockingQueue
newScheduledThreadPool自定义Integer.MAX_VALUE0NANOSECONDSDelayedWorkQueue

2.2 应用场景

  • newFixedThreadPool:线程数一般根据CPU核数设置,用于处理CPU密集型任务,保证在CPU在长期被工作线程使用的场景下,不过多分配线程。
  • newCachedThreadPool:任务提交速度大于执行速度时,又不期望进入等待。每次提交直接创建线程去执行,空闲60s后销毁,保证线程池在空闲时不占用资源。
  • newSingleThreadExecutor:任务串行执行,由于目前大部分时候应用都是多节点部署,真要串行还得配合其他中间件。
  • newScheduledThreadPool :延迟执行任务,并且限制使用线程数的场景。

2.3 注意事项

  1. 不建议使用默认线程池,需要时请根据自己的需求,自行调整参数;
  2. 项目内避免不做区分的混用线程池,特别是核心任务,避免核心任务被次要任务拖垮;
  3. 使用线程池请自定义命名,方便问题排查;
  4. 线程数请做限制,避免意外情况任务过多导致OOM,反例newCachedThreadPool。无界队列同理
  5. 线程池使用完记得关闭
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值