为什么不同的线程池会选择不同类型的队列?

先看看几种线程池使用的都是哪种类型的对列,同时看看相应的源码,这里说的几种线程池不包括WorkStealingPool

线程池 队列
FixedThreadPool LinkedBlockingQueue

在这里插入图片描述

线程池 队列
SingleThreadExecutor LinkedBlockingQueue

在这里插入图片描述

线程池 队列
CachedThreadPool SynchronousQueue

在这里插入图片描述

线程池 队列
ScheduledThreadPool DelayedWorkQueue

在这里插入图片描述
在这里插入图片描述

线程池 队列
SingleThreadScheduledExecutor DelayedWorkQueue

在这里插入图片描述
在这里插入图片描述

可以看到线程池的类型有5种之多,但是相对应的队列只有3种,接下来分析下为什么不同线程池会选择不同类型的队列

LinkedBlockingQueue

这个队列,是无界队列,也可以理解成队列是无限大的,使用它的线程池有FixedThreadPool和SingleThreadExecutor,从以上截图的源码里可以发现,FixedThreadPool以及SingleThreadExecutor两种类型的线程池,他们的核心线程数和最大线程数是一样的,这样是不是可以理解成,哪怕任务再多,也只有核心线程数目的线程在执行任务,那多出来的任务怎么办,只能存在队列了,但问题是,任务那么多,又没有新的线程来帮忙,放在有界的队列会不会根本不够,所以只好选择无界队列LinkedBlockingQueue来配合这两个类型的线程池了。

SynchronousQueue

这个队列是一个不存储元素的队列,它只负责传递消息。那么CachedThreadPool为什么会采用这种类型的队列呢,先看上图截图的相关源码,CachedThreadPool默认的核心线程数是0,它的最大线程数为Integer.MAX_VALUE,可以认为是无限大,所以一旦有任务需要处理,这种类型的线程池就会直接创建一个线程去执行,并不会把任务存储在队列中,因为线程数完全能够支持执行所有的任务,那么就无需存储在队列里,队列起个传递消息的效果就好了。

DelayedWorkQueue

这种队列的内部元素会按照延迟时间的长短对任务进行排序,延时时间越短地就排在队列的前面,越先被执行,他的内部采用的是“堆”的数据结构。ScheduledThreadPool和SingleThreadScheduledExecutor这两种类型的线程池就用到该队列。这两种线程池要的效果是可以延迟的执行任务,是以时间为单位来决定任务的执行顺序的,刚好DelayedWorkQueue队列就有把任务按时间进行排序的能力,所以一拍即合,这两种线程池就使用DelayedWorkQueue队列了。

原创文章 358 获赞 387 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_38106322/article/details/105651464