线程池Thread Pool

为什么使用线程池

池化思想,线程池的主要目的是减少在创建和销毁线程时所花费的开销和资源,提高程序性能、提高资源利用率,同时也提供了对并发执行任务的更好管理,例如控制线程数量。

优势:线程复用、资源控制、方便管理。

线程池七大参数

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);

corePoolSize:核心线程数,即使线程处于空闲状态也不会被回收

maximumPoolSize:最大线程数,在核心线程和队列均满且线程数量未达到最大线程数时,创建新的线程处理任务。新建的线程在空闲超过设定的时间后,会销毁线程。

keepAliveTime和TimeUnit:空闲的非核心线程的存活时间及时间单位

BlockingQueue:阻塞队列,当核心线程全在执行任务时,新来的任务保存到阻塞队列中等待执行

ThreadFactory:创建线程的工厂,使用默认的工厂即可,也可以自定义工厂,通常设置自定义的线程名称,查看日志排查问题时来达到区分线程的效果。

RejectedExecutionHandler:拒绝策略,在线程池已经创建最大的线程数量且队列满时,新提交的任务的拒绝策略。

核心线程数和最大线程数怎么设置?

根据服务器的配置和当前服务类型来选择,可参考的配置如下:

- CPU密集型服务(使用CPU资源较大):核心线程数配置为服务器处理器的核心数,最大线程数可以在此基础上稍微增加
- IO密集型服务(IO过程中线程被挂起,其他线程可以继续执行,消耗CPU资源较少):核心线程数配置为服务器处理器的核心数的两倍,最大线程数在此基础上稍微增加

例如4核16G的服务器,当前服务两个线程池可以这样配置:

- 通用线程池:3核心,6最大线程;定时任务线程池:1核心,4最大线程。

生产环境配置过程中,根据压测情况来配置合适的线程数。

非核心线程存活时间如何设置

根据服务来配置,可参考如下:

- 短期高并发场景:设置较短的存活时间30s或1min,尽快释放资源,减少不必要的线程占用。
- 长期稳定的负载:选择较长的时间2min或5min,减少线程的频繁创建和销毁,提高资源利用率。

生产环境配置过程中,根据压测情况来配置合适的存活时间。

选择哪种阻塞队列?

最常用的是 ArrayBlockingQueue 和 LinkedBlockingQueue:

- ArrayBlockingQueue 适用于需要严格控制队列容量的场景,使用数组实现,使用一个互斥锁来保护整个队列。
- LinkedBlockingQueue 适用于需要高性能队列的场景,使用链表实现,使用两个锁来分别保护 put 和 take操作,减少了锁的竞争,提高了并发性能,并且可以通过指定容量来避免内存溢出。
- 如果应用场景需要支持优先级排序,那么 PriorityBlockingQueue 也是一个很好的选择。如果需要创建固定大小的线程池,并且希望线程间直接传递任务,那么 SynchronousQueue 也非常有用。
线程工厂

可以自定义线程工厂,设置新建线程的属性和状态,比如修改线程前缀名称,设置是否线程为守护线程。一般执行定时任务后台任务之类的可以设置为守护进程,执行业务核心逻辑的线程默认非守护线程。

拒绝策略有哪些?该怎么选择?
  • AbortPolicy:拒绝当前任务并抛出异常
  • CallerRunsPolicy:拒绝当前任务,将任务交个调用线程自己执行
  • DiscardPolicy:拒绝当前任务
  • DiscardOldestPolicy:将队列中第一个任务抛弃,将当前任务加到队列尾部

分情况来选择:

如果任务可以丢弃,选择DiscardPolicy或者DiscardOldestPolicy

如果任务不能丢弃,且调用线程执行任务在大多数情况下系统可以负担,选用CallerRunsPolicy

如果任务不能丢弃,也可以选用AbortPolicy,在抛出异常后执行补偿逻辑(存入数据库或其他操作)

也可以自定义拒绝策略来实现自定义的需求

线程池的执行流程

画板

JUC中提供了几种线程池实现,他们都有什么区别?

画板

线程池的状态有哪几种?他们之间如何转换的?

// runState is stored in the high-order bits

运行状态保存在高(3)位里,COUNT_BITS = Integer. SIZE - 3 == 29

private static final int RUNNING = -1 << COUNT_BITS;

private static final int SHUTDOWN = 0 << COUNT_BITS;

private static final int STOP = 1 << COUNT_BITS;

private static final int TIDYING = 2 << COUNT_BITS;

private static final int TERMINATED = 3 << COUNT_BITS;

画板

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值