网站首页 > 技术文章 正文
本章主要内容来源于
Java Threads(3rd Edition)(OReilly) author:Scott Oaks, Henry Wong
Java concurrent in practice author:Brian Goetz / Tim Peierls / Joshua Bloch / Joseph Bowbeer / David Holmes / Doug Lea
还有很多地方需要深入研究以及没有理解到位的地方,但是我会尽最大的努力做到知识全面化,为大家带来更详细,更深入的知识,如果有那些地方您觉得不对,希望可以在评论区指出,小编会感激不尽!!!
1. 线程池有那些好处
对于开发者来说,如果没有线程池我们需要创建大量的Thread,不论是开发者还是应用程序这都不是一个好的现象。而有了线程池我们只需要提交Runnable(Callable)这样的对象到线程池中,省去了对线程生命周期则的管理,并且实现了线程的复用。线程池中还维护了一个BlockingQueue,这样使得消费者和提供者可以分离,使开发者只需要关注业务逻辑即可,这样使得代码更加内聚,更加便于维护,当然这也只是解决了大部分问题,有时候线程池中提交任务的速度快于消费者处理业务的话,我们也需要拒绝新的任务到线程池,直到线程池中有空闲的位置,也有一些任务并不适用于线程池比如大文件的读取。
2. 线程池核心参数设置以及详解
接下来我们讨论下线程池的构造,线程池有很多构造函数,下面的构造函数是参数最齐的,已经覆盖所有构造函数的参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);
}
首先说下各个参数含义:
coreSize 核心线程数
maximumPoolSize 最大线程数
keepAliveTime 线程存活时间
Unit 线程存活时间的时间单位比如秒,毫秒等
workQueue blockQueue是专门为高并发设计的容器
threadFactory 可以更线程默认的名字,状态,线程组,优先级策略
Handler 拒绝策略
总的来说线程池分为四个部分,分别是控制线程数量的coreSize,maximumPoolSize参数;控制队列的workQueue;控制线程存活时间keepAliveTime,unit和控制线程信息的threadFactory;最后是线程的拒绝策略handler,可以说线程池主要就是这四部分,除了构造函数之外ThreadPoolExecutor也提供了方法对核心参数进行修改,为了更进一步讨论,请看以下代码,在线程池中核心线程数设置为5,最大线程数为10,提交了110个任务
当我们创建线程池的时候,还没有提交任务到线程池,其实线程池中的是没有线程的,当提交了第一个任务,线程池则会创建一个线程,直到达到了核心线程数,这个时候如果核心线程数有空闲的新提交的任务会交给空闲的线程,如果没有空闲的线程则会提交到工作队列(BlockingQueue)中,如果Blockingqueue 如果已经满了,则创建新的线程,直到达到最大线程数,如果这个时候消费者处理速度还没有追上提供者,则会调用拒绝策略,拒绝新任务提交。所以本例中线程池一共可以容纳110个任务,工作队列容纳100个任务,核心线程处理5个,工作队列达到边界,创建新的线程到最大线程数.所以可能容乃110个任务,如果提交到第111个,线程池则会拒绝任务的提交。
还有就是工作队列(BlockingQueue)页影响着线程池的工作方式,上面例子中我们使用的是有界的LinkedBlockingQueue,java5开始提供了一系列的Blockingqueue有ArrayBlockingQueue,SynchronousQueue,LinkedBlockingQueue,PriorityBlockingQueue,DelayQueue等
SynchronousQueue:实际上并不是真正意义上的队列,SynchronousQueue更多的是在线程之间共享任务,工作队列的大小实际上是0,我们可以看到,当提交的任务超过11个时,由于消费者的处理能力追不上提供者,所以线程池拒绝了新的任务,因为使用SynchronousQueue处理任务的时候SynchronousQueue并不会排队,要么立即处理要么立即失败。
DelayQueue:延迟队列,实际上这个BlockingQueue并不适用于ThreadPoolExecutor,因为DelayQueue是延迟队列,而另一个线程池正是使用DelayQueue,才实现了定时调用的功能,这个线程池就是ScheduledThreadPoolExecutor
LinkedBlockingQueue:无边界队列:
注意LinkedBlockingQueue没有设置边界就是无限容量。在这种情况下,总是将任务添加到队列中成功,这意味着线程池不会创建超过M的线程和从不拒绝任务。
LinkedBlockingQueue(100),ArrayBlockingQueue,PriorityBlockingQueue有界队列:
假设队列P的界限。当任务被添加到池中时,它将创建线程,直到达到M个线程。此时,它开始将任务排队,直到等待的任务数达到P。随着添加更多任务,线程池开始添加线程,直到达到N个线程。如果N个线程处于活动状态,而P个任务处于队列中,则其他任务被拒绝。
PriorityBlockingQueue 是带有优先级的有界队列,默认大小为11个
那么我们应该如何设置这些参数呢?
如果线程数量过大则会在相对较小的CPU和内存中发生竞争,如果过小则会由很多空闲的CPU,导致吞吐量的不足。所以我们需要分析环境中有多少个CPU,内存是多大,是计算密集型的操作还是IO密集型的操作。对于计算密集型的任务,当前线程数量为CPU数量+1为最优。对于IO密集型或者有阻塞的任务,由于线程并不会一致执行,因此线程池应该过大,推荐的计算公式为
CPU利用率=CPU数量x目标CPU利用率x(1+(等待时长/计算时长))
CPU数量可以通过 Runtime.getRuntime().availableProcessors()获取
- 上一篇: 线程池中各个参数如何合理设置 线程池各个参数含义
- 下一篇: 如何区分IO密集型、CPU密集型任务?
猜你喜欢
- 2024-10-22 线程池调优之动态参数配置 动态设置线程池大小
- 2024-10-22 java线程池参数及使用 java线程池的用法
- 2024-10-22 面试官:说说你对线程池的了解 线程池实现原理面试
- 2024-10-22 「每日分享」高阶程序员需要掌握的常见性能优化策略
- 2024-10-22 池化技术学习 池化方法
- 2024-10-22 「Java基础」「多线程」-线程池 java多个线程池
- 2024-10-22 线程池配置的常见误区 线程池配置参数有哪些
- 2024-10-22 创建线程池参数有哪些作用? 创建线程池的7个参数
- 2024-10-22 一文搞懂!多线程之间的通信及线程池
- 2024-10-22 码农大叔带你——解析线程池 线程池的主要处理流程
你 发表评论:
欢迎- 最近发表
-
- 吴谨言专访大反转!痛批耍大牌后竟翻红,六公主七连发力显真诚
- 港股2月28日物业股涨幅榜:CHINAOVSPPT涨1.72%位居首位
- 港股2月28日物业股午盘:CHINAOVSPPT涨1.72%位居首位
- 港股3月2日物业股涨幅榜:CHINAOVSPPT涨1.03%位居首位
- 港股3月2日物业股午盘:CHINAOVSPPT涨1.03%
- 天赋与心痛的背后:邓鸣贺成长悲剧引发的深刻反思
- 冯小刚女儿徐朵追星范丞丞 同框合照曝光惹人羡,回应网友尽显亲民
- “资本大佬”王冉:51岁娶小17岁童瑶,并承诺余生为娇妻保驾护航
- 港股3月2日物业股午盘:CHINAOVSPPT涨1.03%位居首位
- 「IT之家开箱」vivo S15 图赏:双镜云窗,盛夏风光
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)