ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java并发编程(十一)——线程池内部结构详解

2021-12-28 23:03:53  阅读:148  来源: 互联网

标签:java DelayedWorkQueue 队列 阻塞 SynchronousQueue 任务 详解 线程


前言

前面我们学习了几种常见的线程池的一些常见参数及基本使用,但对于底层的原理还是不太了解。本文我们来了解下线程池的内部结构,重点关注线程池内部的阻塞队列。

线程池内部结构

线程池内部结构

  1. 线程池管理器:

    主要负责线程池的创建、销毁、添加任务等管理操作,它是整个线程池的大管家。

  2. 工作线程:

    图中的线程 t0~t9,这些线程勤勤恳恳地从任务队列中获取任务并执行。

  3. 任务队列
    作为一种缓冲机制,线程池会把当下没有处理的任务放入任务队列中,由于多线程同时从任务队列中获取任务是并发场景,此时就需要任务队列满足线程安全的要求,所以线程池中任务队列采用 BlockingQueue 来保障线程安全

  4. 任务
    任务要求实现统一的接口,以便工作线程可以处理和执行。

阻塞队列

常见的线程池及对应内部所用的阻塞队列如下表所示:

线程池所用阻塞队列
FixedThreadPoolLinkedBlockingQueue
SingleThreadExecutorLinkedBlockingQueue
CachedThreadPoolSynchronousQueue
ScheduledThreadPoolDelayedWorkQueue
SingleThreadScheduledExecutorDelayedWorkQueue

5种线程池一共用了三种阻塞队列,LinkedBlockingQueue、SynchronousQueue、DelayedWorkQueue。

LinkedBlockingQueue

	对于 FixedThreadPool 和 SingleThreadExector 而言,它们使用的阻塞队列是容量为**Integer.MAX_VALUE** 的 LinkedBlockingQueue,可以认为是无界队列。由于 FixedThreadPool 线程池的线程数是固定的,所以没有办法增加特别多的线程来处理任务,这时就需要 LinkedBlockingQueue 这样一个没有容量限制的阻塞队列来存放任务。

image-20210201180540335

注意:由于线程池的任务队列永远不会放满,所以线程池只会创建核心线程数量的线程,所以此时的最大线程数对线程池来说没有意义,因为并不会触发生成多于核心线程数的线程。

SynchronousQueue

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

看SynchronousQueue的源码可知,它内部队列的长度始终为0,不存储任何任务。

image-20210201180303113

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

DelayedWorkQueue

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

DelayedWorkQueue 的特点是内部元素并不是按照放入的时间排序,而是会按照延迟的时间长短对任务进行排序,内部采用的是**“堆”**的数据结构。

之所以线程池 ScheduledThreadPool 和 SingleThreadScheduledExecutor 选择 DelayedWorkQueue,是因为它们本身正是基于时间执行任务的,而延迟队列正好可以把任务按时间进行排序,方便任务的执行。

总结

线程池主要由线程管理器、工作线程、任务队列、任务组成,其中线程管理器是管理工作线程的,任务队列是管理任务的。常见的几种线程池使用到的任务队列有LinkedBlockingQueue、SynchronousQueue、DelayedWorkQueue三种。

标签:java,DelayedWorkQueue,队列,阻塞,SynchronousQueue,任务,详解,线程
来源: https://blog.csdn.net/yongbutingxide/article/details/122204793

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有