java 线程池

线程池构造函数的参数

workQueue有三种类型:
1.直接交接SynchronousQueue(无容量,直接将任务交给线程)
2.无界队列LinkedBlockingQueue (无边界队列,永远填不满)
3.有界队列ArrayBlockingQueue (有数队列,固定大小)

添加线程规则

  1. 如果线程数小于corePoolSize,即时其他工作线程处于空闲状态,也会创建一个新线程来运行新任务。
  2. 如果线程数等于(或大于)corePoolSize但少于maximumPoolSize,则将任务放入队列。
  3. 如果队列已满,并且线程数小于maxPoolSize,则创建一个新线程来运行任务。
  4. 如果队列已满,并且线程数大于或等于maxPoolSize,则拒绝该任务。

在这里插入图片描述

拒绝策略

AbortPolicy:直接抛出RejectedExecutionException异常,并抛弃任务,默认就是这种策略。
DiscardPolicy:直接拒绝任务,但是没有异常提醒。
DiscardOldestPolicy:将队列中最前面的任务丢弃,然后再重新提交被拒绝的任务。这个策略需要适当小心。
CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务

线程的分类

1.newFixedThreadPool

在这里插入图片描述

固定线程池,核心线程数和最大线程数固定相等。源码中可以看出使用的队列为LinkedBlockingQueue,该队列是没有容量上限(Integer.MAX_VALUE)的,所以当请求数越来越多,并且无法及时处理完毕的时候,也就是请求堆积的时候,会容易造成占用大量的内存,可能导致OOM。

2.newSingleThreadExecutor

在这里插入图片描述
可以看出,这里和刚才的newFixedThreadPool原理基本一样,只不过把线程数直接设置成了1,每次只执行一个线程,多余的先存储到工作队列,一个一个执行。所以这也会导致同样的问题,也就是请求堆积的时候,可能会占用大量的内存。

3.newCachedThreadPool

在这里插入图片描述
此线程池核心线程数为0,最大线程数为Integer.MAX_VALUE,超过0个的空闲线程在60秒后销毁,并且队列为SynchronousQueue,因此任务会被直接交给线程处理,无法等待。这里同样有个弊端,由于maximumPoolSize被设置为Integer最大值,所以可能会创建数量非常多的线程,甚至导致OOM。

3.scheduledThreadPool

在这里插入图片描述在这里插入图片描述
指定延时后执行任务或按一定的周期执行任务,即定时任务.
DelayQueue内部封装了一个PriorityQueue,它会根据time的先后时间排序(time小的排在前面),若time相同则根据sequenceNumber排序( sequenceNumber小的排在前面);DelayQueue也是一个无边界队列

线程池里线程数量设定为多少合适?

1.CPU密集型(加密、计算hash等):最佳线程数为CPU核心数的1-2倍左右。
2.耗时IO型(读写数据库、文件、网络读写等):最佳线程数一般会大于cpu核心数很多倍,以JVM线程监控显示繁忙情况为依据,保证线程空闲可以衔接上,参考Brain Goetz推荐的计算方法:
线程数=CPU核心数*(1+平局等待时间/平均工作时间)

停止线程池的正确方法

1.shutdown:会拒绝线程新线程任务的添加,但是如果有执行中的线程和队列中等待执行的线程,会先将执行中和队列里的线程执行完毕,然后停止线程(执行shutdown命令后,无法向线程池中添加新线程)
2.shutdownNow:立即中断所有线程,并将等待执行的线程以List形式返回,用作后续处理(记录日志或者其他线程执行等。。。)
以上俩个方法根据业务选择

今天先到这里。。。
明天和大家分享原子类的知识点。。。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值