[ Java ]中的线程池工作原理,为什么不是先创建线程而是先往阻塞队列里塞任务?

201 天前
 lsk569937453

假设核心线程数为 n,最大线程数为 m 。线程池创建后,就提交了 n 个任务且这 n 个任务一直在执行,没有结束。此时再提交一个任务就会塞到任务队列里。我的疑问是新提交的这个任务为什么不是创建一个新的线程执行?。线程池不是应该首先要保证任务完成吗?

现在的逻辑是"先判断任务队列是否满再判断是否达到最大线程数",这样设计有什么优点呢?

7380 次点击
所在节点    Java
86 条回复
cheng6563
201 天前
会创建新的啊,直到执行中的线程达到 m 才会按策略或阻塞或报错。
codegenerator
201 天前
先创建线程如果线程执行完任务就会空闲,空闲等待一定时间就会销毁
这样会有比较多的线程创建销毁
BiChengfei
201 天前
例子 1:你去银行办业务,银行也只会在队伍超级长的时候,才会开新窗口,也不是只要开始排队就加窗口
例子 2:小明 1 天能处理 5 个 BUG ,新的 BUG 会放在 TODO 队列,TODO 队列长度为 100 ,当陆续进来了 10 个 BUG ,你是等待小明慢慢处理完,还是再招一个人呢
imokkkk
201 天前
具体场景具体分析吧 像 tomcat 线程池就是先创建线程再往队列里丢 web 场景下解决的是大量请求、短连接的场景
NizumaEiji
201 天前
因为创建线程需要消耗系统资源,而系统的资源是有上限的。
orzwalker111
201 天前
合理利用资源。这个得结合业务调整配置,假如配置成 n=5 、m=100 、queue=10 万,而侧重点是想让任务快速提交执行,这个配置可能有问题了
luzemin
201 天前
就是这么一个设计,允许任务排队等一下,你非要说我一下也不想等,那你创建的时候把队列长度设置为 0 就好了。
但 [新建普通线程,执行完又没任务,还要销毁] 这一系列操作带来的开销,可能还超过了 [暂时放在队列稍后就处理]
lsk569937453
201 天前
@codegenerator
```
先创建线程如果线程执行完任务就会空闲,空闲等待一定时间就会销毁
这样会有比较多的线程创建销毁
```
既然你喜欢举例,那我就举一个例子。

我们假设线程池的前 n 个任务非常耗时,一直执行不完
"先判断任务队列是否满再判断是否达到最大线程数":如果任务队列长度是 10w ,那么后续提交的 10w 个任务(执行耗时很短),在任务对列满之前无法执行,需要一直等待在队列中。
lsk569937453
201 天前
@orzwalker111 我使用线程池当然是通过并发让任务快速执行。难道除了"让任务快速提交执行"之外还有其他的选项吗?
TuringHero
201 天前
「线程池不是应该首先要保证任务完成吗?」
并不是。我理解线程池就是为了在一定情况下让任务 等待 / 拒绝 从而避免创建过多线程
veapon
201 天前
因为入队列不需要锁,而创建线程需要锁,这样设计是为了尽量减少创建线程导致的频繁获取锁操作。
muyiluop
201 天前
”我使用线程池当然是通过并发让任务快速执行“,那你就设置队列为 0 。线程池目的就是为了复用已经创建的线程减少线程创建的开销,你想的并发让任务快速执行,可以通过多线程来操作,但这不是线程池的目的。
lsk569937453
201 天前
@veapon 请问我创建线程的时候获取锁耗时 1ms 。而你往阻塞队列塞任务不需要锁,但你任务入队了又不能执行,所以你讨论耗时有什么用呢。
j1132888093
201 天前
@lsk569937453 #8 你说的这个场景是少数情况,而且完全可以增大核心线程数或者减少队列长度来实现,线程池是为了减少开销,直接去判断最大线程数只会增加创建和销毁线程的开销
salmon5
201 天前
这个逻辑其实不合理。计算资源可以扩容解决。
leonshaw
201 天前
@muyiluop 队列为 0 会导致任务超过最大线程数时直接被拒绝
salmon5
201 天前
这个逻辑有点落后了,10-20 年前的思维,现在已经不是物理机时代(资源需要几天才能扩容到位:采购新物理服务器、CPU 、内存)。
hellojukay
201 天前
线程池就是用来控制线程数量不暴涨的,如果系统上任务太多,每个任务都一个线程,那么如果突然来了大量任务,系统上线程数量就会暴涨,操作系统调度的基本单位是线程,那么操作系统大量时间都花在调度线程上,效率非常低,所有任务都不能得到高效的执行。

线程池保证了任务并发的数量,保证每个任务都能获得有效的 CPU 时间片段。
veapon
201 天前
@ lsk569937453 请问我创建线程的时候获取锁耗时 1ms 。而你往阻塞队列塞任务不需要锁,但你任务入队了又不能执行,所以你讨论耗时有什么用呢。
----
你理解的锁问题只有耗时?
InkStone
201 天前
避免频繁的线程创建销毁呗。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1036271

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX