线程池ThreadPoolExecutor
Posted Empty
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池ThreadPoolExecutor相关的知识,希望对你有一定的参考价值。
一 使用线程池的好处
- 降低资源消耗:通过重复使用线程减少线程创建和销毁对资源的造成的消耗。
- 提高响应速度:任务抵达时,可以不需要等待线程的创建就能立即执行。
- 提高线程的可管理性:线程是稀缺资源,无限制的创建会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
二 线程池的参数
1.核心线程数
2.最大线程数
3.超过核心线程数的线程保持时间
4.线程保持时间的单位
5.存放等待线程的队列
6.线程创建工厂
7.线程的饱和策略。
三 线程池的工作原理
新的任务来到,先判断线程内工作线程是否达到核心线程数,如果没有,直接创建线程执行任务。
如果核心线程数已满,队列未满,任务则会加入等待队列。
如果等待队列已满,并且没有达到最大线程数,会创建线程,执行任务。
如果等待队列已满,也已经打到了最大线程数,会触发饱和策略
四 有哪些饱和策略
• ThreadPoolExecutor.AbortPolicy:抛出 RejectedExecutionException来拒绝新任务的处理。
• ThreadPoolExecutor.CallerRunsPolicy:调用执行自己的线程运行任务,也就是直接在调用execute方法的线程中运行(run)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。在当前的调用线程执行任务。提交会延迟。
• ThreadPoolExecutor.DiscardPolicy: 不处理新任务,直接丢弃掉。
• ThreadPoolExecutor.DiscardOldestPolicy: 此策略将丢弃最早的未处理的任务请求。
默认的拒绝策略是AbortPolicy 抛出RejectedExecutionException。
五 一些对比
1.Runnable VS Callable
Runnable 不会返回结果或者抛出异常、Callable可以。
2.execute() Vs submit();
execute() 提交不需要返回值的任务。
submit() 提交需要返回值得任务。会返回Future<T> 对象。
可以调用 future.get() 获取结果,get()方法会阻塞当前线程。
get(long timeout,TimeUnit unit)方法可以阻塞一段时间后就返回,但线程可能并未完成,拿不到结果。
3.shutdown() Vs shutdownNow()
shutdown: 关闭线程池,线程池状态变为shutdown,不接受新任务,但会等待队列里的任务执行完毕。
shutdownNow : 关闭线程池,线程池状态变为STOP,会终止正在运行的任务,停止处理排队的任务,并返回等待的List。
4.isTerminated() Vs isShutDown();
isShutDown 当调用 shutdown()之后就会返回true;
isTerminated() ,当调用shutdown()之后,等所有任务执行完毕才会返回true;
六 几种常见的线程池及问题
1.FixedThreadPool 固定线程池。核心线程数等于最大线程数,无界队列 Integer.MAX_VALUE 任务多可能OOM
2.SingleThreadPool 单例线程池。 核心线程数和最大线程数为1 无界队列 任务多可能OOM
3.cacheThreadPool 缓存线程池。核心线程数为0 最大线程数为Integer.MAX_VALUE 同步队列,线程过多
七 核心线程数的大小设置
计算密集型:CPU个数+1。
I/O密集型:2倍CPU个数。
以上是关于线程池ThreadPoolExecutor的主要内容,如果未能解决你的问题,请参考以下文章