如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?
在Java中可以通过线程池来达到这样的效果。
1、我们的应用更多的都是多线程处理业务,线程数量很多,创建和销毁线程消耗系统资源,所以频繁创建和销毁线程销毁处理影响系统效率
3、期望一种东西对线程进行一些简单的管理(线程的生命周期)
1、保持线程处于存活状态(就绪,运行或者阻塞)
2、控制并发的数量()
3、设置线程的状态,管理线程
线程池 最小的线程数量
最大的线程数量
闲置时间 有单位的
任务队列
拒绝
corePoolSize没有核心线程数量;maxPoolSize最大线程数量为int最大值
适用:短期异步小程序或者负载较轻服务器
核心线程数量等于最大线程数量
适用:执行长期的任务
核心线程数量等于最大线程数量 都等于1
适用:一个任务一个任务执行
最大线程数是int最大值
适用:周期性执行任务的场景(定期同步数据)
参数:corePoolSize:核心线程数(最小存活的工作线程数量)
maxPoolSize:最大线程数
keepAliveTime:存活时间
timeUnit:单位
workQueue:阻塞队列
threadFactory线程工厂
handler:拒绝
当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:
`ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 ``ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 ``ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) ``ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 `发短信、发邮件、清除日志
本节来讨论一个比较重要的话题:如何合理配置线程池大小,仅供参考。
一般需要根据任务的类型来配置线程池大小:
如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 NCPU+1
如果是IO密集型任务,参考值可以设置为2**N*CPU
当然,这只是一个参考值,具体的设置还需要根据实际情况进行调整,比如可以先将线程池大小设置为参考值,再观察任务运行情况和系统负载、资源利用率来进行适当调整。