JAVA线程池简介

一、线程池的优势
1.节约系统资源。我们知道线程的创建和销毁都是要耗费系统资源的,我们利用线程池可以重复利用线程,避免了线程的过多创建和消耗。
2.减少用户响应时间。我们执行一个任务,一般要经过线程创建、任务执行、线程销毁三个步骤,每个步骤都是要消耗时间的,我们用线程池可以节约创建和销毁时间,从而减少用户响应时间
3.便于管理线程。我们知道线程属于系统的稀缺资源,如果因为编写代码的问题,无限创建线程,会大量消耗系统资源,甚至系统崩溃。市容线程池可以统一管理线程的创建和销毁,便于监控、调优。
二、线程核心类ThreadPoolExecutor的类关系
在这里插入图片描述
三、ThreadPoolExecutor各个参数的含义
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize, long keepAliveTime,TimeUnit unit,
BlockingQueue workQueue) {}
corePoolSize:线程池核心线程数。
maximumPoolSize:最大线程数。
keepAliveTime:空闲线程等待销毁时间,该参数一般在线程数大于核心线程数时才有用。
TimeUnit :keepAliveTime的单位
BlockingQueue:阻塞队列
threadFactory:创建线程的工厂,我们可以通过它自定义一些线程属性,比如:自定义创建线程每次,一般默认“pool-数字 -thread-数字”,还可以设置守护线程等等。
RejectedExecutionHandler:线程池饱和策略。
(1)AbortPolicy:默认策略,抛出异常
(2)CallerRunsPolicy:谁提交任务谁去执行,不用线程池线程执行
(3)DiscardOldestPolicy:把阻塞队列的头任务干掉,执行该任务
(4)DiscardPolicy:直接舍弃该任务
当然,也可以根据自己业务实际情况实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。
参数说完,我们看看线程池如何用上面参数来工作
1.当线程池接收到一个新任务,会首先判断线程池里的线程数量是否达到corePoolSize,如果小于corePoolSize,会创建一个新线程去执行该任务;
2.如果线程数大于corePoolSize但是小于maximumPoolSize会把该任务放入BlockingQueue阻塞队列中;
3.如果阻塞队列已经满了,就会创建新线程去执行该任务
4.如果线程数达到了maximumPoolSize,这是会根据定于的饱和策略去执行对应操作,调用 RejectedExecutionHandler.rejectedExecution()方法
注意:BlockingQueue一般我们最好用有界队列,用无界队列会有一下影响
1.maximumPoolSize和keepAliveTime将会是无效参数
2.无界意味着不可控,可能会耗尽系统资源,即使使用有界队列,我们也应该定义一个合适的大小
常用阻塞队列:
·ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
·LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
·PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
·DelayQueue:一个使用优先级队列实现的无界阻塞队列。
·SynchronousQueue:一个不存储元素的阻塞队列。
·LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
·LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
以上的阻塞队列都实现了 BlockingQueue 接口,也都是线程安全的。

四、提交任务及一些方法
beforeExecute():每个任务执行前都会调用
afterExecute():每个任务执行后都会调用
terminated():调用 shutdown 方法后则会调用
execute():提交无返回值的任务
submit():提交的任务有返回值。返回一个 future 类型的对象,通过这个 future 对象可以判断任务是否执行成功,并且可以通过 future 的 get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用 get (long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这 时候有可能任务没有执行完
五、关闭线程池
可以通过shutdown 或 shutdownNow方法来关闭线程池。它们原理都是,遍历线程池中的工作线程,然后调用每个线程的 interrupt 方法来中断 线程,所以无法响应中断的任务可能永远无法终止。但是shutdownNow是将线程池状态设置成STOP,试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表,而 shutdown 只是将线程池的状态设置成 SHUTDOWN 状态,然后中断所有没有正在执行任务的线程。我们通常调用 shutdown 方法来关闭线程池,如果任务不一定要执行完, 则可以调用 shutdownNow 方法。
六、合理配置线程池
首先分析任务特性,一般分为cpu密集型、IO密集型、混合型
cpu密集型:cpu核心(逻辑数)+ 1
《Java并发编程实战》这么说:
计算(CPU)密集型的线程恰好在某时因为发生一个页错误或者因其他原因而暂停,刚好有一个“额外”的线程,可以确保在这种情况下CPU周期不会中断工作。
IO密集型:2*cpu核心(逻辑数)
混合型:NCPU * UCPU * (1 + W/C)
NCPU 是处理器的核的数目
UCPU 是期望的 CPU 利用率(该值应该介于 0 和 1 之间)
W/C 是等待时间与计算时间的比率 ,等待时间与计算时间我们在 Linux 下使用相关的 vmstat 命令或者 top 命令查看
七、预定义线程池
1.FixedThreadPool
创建使用固定线程数的 FixedThreadPool 的 API。适用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景FixedThreadPool 的 corePoolSize 和 maximumPoolSize 都被设置为创建 FixedThreadPool 时指定的参数 nThreads。 当线程池中的线程数大于corePoolSize 时,keepAliveTime 为多余的空闲线程等待新任务的 最长时间,超过这个时间后多余的线程将被终止。这里把 keepAliveTime 设 置为 0L,意味着多余的空闲线程会被立即终止。
FixedThreadPool 使用有界队列 LinkedBlockingQueue 作为线程池的工作队列 (队列的容量为 Integer.MAX_VALUE)。 2.SingleThreadExecutor
创建使用单个线程的 SingleThread-Executor 的 API,用于需要保证顺序地执行各个任务;并且在任意时间点,不会有多个线程是活动的应用场景。 corePoolSize 和 maximumPoolSize 被设置为 1。其他参数与 FixedThreadPool 相同。
SingleThreadExecutor 使用有界队列 LinkedBlockingQueue 作为线程池的工 作队列(队列的容量为 Integer.MAX_VALUE)。 3.CachedThreadPool
创建一个会根据需要创建新线程的 CachedThreadPool 的 API。大小无界的线 程池,适用于执行很多的短期异步任务的小程序,或者是负载较轻的服务器。 corePoolSize 被设置为 0,即 corePool 为空;maximumPoolSize 被设置为 Integer.MAX_VALUE。这里keepAliveTime 设置为 60L,意味着 CachedThreadPool 中的空闲线程等待新任务的最长时间为60秒,空闲线程超过60秒后将会被终止。
FixedThreadPool 和 SingleThreadExecutor 使用有界队列 LinkedBlockingQueue 作为线程池的工作队列。
CachedThreadPool 使用没有容量的 SynchronousQueue 作为线程池的工作队列,但 CachedThreadPool 的 maximumPool 是无界的。这意味着,如果主线程提交任务的速度高于 maximumPool 中线程处理任务的速度时, CachedThreadPool 会不断创建新线程。极端情况下,CachedThreadPool 会因为创 建过多线程而耗尽 CPU 和内存资源。
4.WorkStealingPool
利用所有运行的处理器数目来创建一个工作窃取的线程池,使用 forkjoin 实 现
5.ScheduledThreadPoolExecutor
使用工厂类 Executors 来创建。Executors 可以创建 2 种类型的 ScheduledThreadPoolExecutor
(1)ScheduledThreadPoolExecutor。包含若干个线程的 ScheduledThreadPoolExecutor。 适用于需要多个后台线程执行周期任务,同时 为了满足资源管理的需求而需要限制后台线程的数量的应用场景
(2)SingleThreadScheduledExecutor。只包含一个线程的 ScheduledThreadPoolExecutor。适用于需要单个后台线程执行周期任务,同 时需要保证顺序地执行各个任务的应用场景

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值