线程池常用的阻塞队列有哪些?

线程池常用的阻塞队列有哪些?

文章目录

  • 线程池常用的阻塞队列有哪些?
    • 1.线程池的内部结构
    • 2.阻塞队列
    • 3.LinkedBlockingQueue
    • 4.SynchronousQueue
    • 5.DelayedWorkQueue
    • 6.参考

1.线程池的内部结构

线程池常用的阻塞队列有哪些?_第1张图片
线程池内部由四部分组成

  • 第一部分是线程池管理器,主要负责管理线程池的创建、销毁、添加任务等管理操作。

  • 第二部分是工作线程,它又分为核心工作线程和非核心工作线程。

  • 第三部分是任务队列,作为一种缓冲机制,会将超过核心线程数的任务放到任务队列中,等待执行;由于多线程同时从任务队列中获取任务是并发场景,此时就需要任务队列满足线程安全的要求,所以线程池中任务队列采用 BlockingQueue 来保障线程安全。

  • 第四部分是任务,任务要求实现统一的接口,以便工作线程可以处理和执行。

2.阻塞队列

线程池对应的阻塞队列

线程池 阻塞队列
FixedThreadPool LinkedBlockingQueue
SingleThreadExecutor LinkedBlockingQueue
CachedThreadPool SynchronousQueue
ScheduledThreadPool DelayedWorkQueue
SingleThreadScheduledExecutor DelayedWorkQueue

3.LinkedBlockingQueue

第一种阻塞队列是 LinkedBlockingQueue,它的容量是 Integer.MAX_VALUE,为 231 -1 ,是一个非常大的值,可以认为是无界队列。

FixedThreadPool 和 SingleThreadExecutor 线程池的线程数是固定的,所以没有办法增加特别多的线程来处理任务,这时就需要 LinkedBlockingQueue 这样一个没有容量限制的阻塞队列来存放任务。

4.SynchronousQueue

第二种阻塞队列是 SynchronousQueue,对应的线程池是 CachedThreadPool。线程池 CachedThreadPool 的最大线程数是 Integer.MAX_VALUE,可以理解为线程数是可以无限扩展的。

CachedThreadPool 和上一种线程池 FixedThreadPool 的情况恰恰相反,FixedThreadPool 的情况是阻塞队列的容量是无限的,而这里 CachedThreadPool 是线程数可以无限扩展,所以 CachedThreadPool 线程池并不需要一个任务队列来存储任务,因为一旦有任务被提交就直接转发给线程或者创建新线程来执行,而不需要另外保存它们。

我们自己创建使用 SynchronousQueue 的线程池时,如果不希望任务被拒绝,那么就需要注意设置最大线程数要尽可能大一些,以免发生任务数大于最大线程数时,没办法把任务放到队列中也没有足够线程来执行任务的情况。

5.DelayedWorkQueue

第三种阻塞队列是DelayedWorkQueue,它对应的线程池分别是 ScheduledThreadPool 和 SingleThreadScheduledExecutor,这两种线程池的最大特点就是可以延迟执行任务,比如说一定时间后执行任务或是每隔一定的时间执行一次任务。

DelayedWorkQueue 的特点是内部元素并不是按照放入的时间排序,而是会按照延迟的时间长短对任务进行排序,内部采用的是“堆”的数据结构(堆的应用之一就是 优先级队列)。之所以线程池 ScheduledThreadPool 和 SingleThreadScheduledExecutor 选择 DelayedWorkQueue,是因为它们本身正是基于时间执行任务的,而延迟队列正好可以把任务按时间进行排序,方便任务的执行。

6.参考

  • 《Java 并发编程 78 讲》- 徐隆曦

你可能感兴趣的:(Java并发编程,线程池,阻塞队列)