发布于2021-05-30 20:06 阅读(1640) 评论(0) 点赞(6) 收藏(5)
线程池可以理解为一个具有多个线程的线程集合.
corePoolSize 核心线程数,没达到核心线程数时,会创建新的线程。当达到核心线程数时,任务会进去队列
maximumPoolSize 最大线程数,可以为Integer.MAX_VALUE 21亿。当达到核心线程数且队列满了的时候,会去创建额外的线程来执行任务,最多不超过最大线程数
keepAliveTime 存活时间,当任务处理完成,额外的线程存活一段时间后,会自行销毁。空闲等待时间(该参数默认对核心线程无效,当allowCoreThreadTimeOut手动设置为true时,核心线程超过存活时间后才会被销毁)
TimeUnit 空闲等待时间的单位
BlockingQueue :任务进来,如果核心线程数满了,则任务进入队列中等待。
ThreadFactory 线程创建工厂
RejectExecutionHandler拒绝策略,当最大线程数满了并且队列也满了的时候,如果再有任务进来就会启用拒绝策略。
参考源码
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default thread factory and rejected execution handler.
* It may be more convenient to use one of the {@link Executors} factory
* methods instead of this general purpose constructor.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
通过Executors工具类创建指定线程池
通过 new ThreadPoolExecutor()
自定义线程池,传入指定参数
newFixedThreadPool():固定线程数的线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
线程池特点:
缺点
使用场景
newFixedThreadPool 适用于处理CPU密集型的任务,确保CPU在长期被工作线程使用的情况下,尽可能的少的分配线程,即适用执行长期的任务。
newCachedThreadPool()
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
线程池特点:
缺点
如果任务的提交速度大于线程处理任务的速度,那么就会不断地创建新线程极端情况下会耗尽CPU和内存资源
CachedThreadPool
允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致 OOM。
任务队列采用的是SynchronousQueue,这个队列是无法插入任务的,一有任务立即执行
使用场景
适用于并发执行大量短期的小任务。
newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
线程池特点
缺点
使用场景
newScheduledThreadPool()
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
线程池特点
使用场景
周期性执行任务的场景,需要限制线程数量的场景
线程池被创建后如果没有任务过来,是不会有线程的。
线程预热可以使用以下两个方法
1.只启动一个线程预热
2.全部启动预热
参考源码
//记录线程池的状态,已经线程池中线程的个数,初始化状态为 Running
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//线程池的五种状态
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;
1、RUNNING
2、ShutDown
状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
状态切换:调用线程池的shutdown() 时,线程池由RUNNING -> SHUTDOWN。
3、STOP
状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
状态切换:调用线程池的shutdownNow() 时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
4、tidying
状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。
当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
5、 TERMINATED(terminated)
状态说明:线程池彻底终止,就变成TERMINATED状态。
状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
AbortPolicy(默认),直接抛出一个类型为 RejectedExecutionException 的 RuntimeException异常阻止系统的正常运行。
DiscardPolicy:直接丢弃任务,不给予任何处理也不抛出异常。如果允许任务丢失的话,这是最好的方案。
DiscardOldestPolicy,抛弃队列中等待时间最长的任务,然后把当前任务加入队列中尝试再次提交任务。
CallerRunsPolicy:"调用者运行"一种调节机制,该策略既不会抛弃任务也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。
判断当前任务是CPU 密集型还是 IO 密集型
公式
1. 方法来源不同
execut()是在线程池的顶级接口Executor中定义的,而且只有这一个接口,可见这个方法的重要性。
public interface Executor {
void execute(Runnable command);
}
在ThreadPoolExecutor类中有它的具体实现。
submit()是在ExecutorService接口中定义的,并定义了三种重载方式,具体可以查看JDK文档
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
2. 接受参数不同
execute()
方法只能接收实现Runnable
接口类型的任务
submit()
方法则既可以接收Runnable
类型的任务,也可以接收Callable
类型的任务。
3. 返回值不同
execute()
的返回值是void
,线程提交后不能得到线程的返回值。
submit()
的返回值是Future
,通过Future的get()
方法可以获取到线程执行的返回值,get()
方法是同步的,执行get()方法时,如果线程还没执行完,会同步等待,直到线程执行完成。
虽然
submit()
方法可以提交Runnable
类型的参数,但执行Future方法的get()时,线程执行完会返回null,不会有实际的返回值,这是因为Runable本来就没有返回值
4. 对于异常处理不同
execute在执行任务时,如果遇到异常会直接抛出,
而submit不会直接抛出,只有在调用Future的get方法获取返回值时,才会抛出异常。
我是 CRUD速写大师,未来的日子里会不断更新出对大家有益的博文,期待大家的关注!!!
创作不易,如果这篇博文对各位有帮助,希望各位小伙伴可以点赞和关注我哦,感谢支持,我们下次再见~~~
分享大纲
更多精彩内容分享,请点击 Hello World (●’◡’●)
原文链接:https://blog.csdn.net/llllllkkkkkooooo/article/details/117391081
作者:你莫说是我
链接:http://www.phpheidong.com/blog/article/86863/df3f37866f554a4910f4/
来源:php黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 php黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-4
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!