通俗易懂,各常用线程池的执行 流程图

作者:林冠宏 / 指尖下的幽灵

掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8

博客:http://www.cnblogs.com/linguanh/

GitHub : https://github.com/af913337456/

有时候花了大把时间去看一些东西却看不懂,是很 “ 蓝瘦 ” 的,花时间也是投资。

本文适合:

  • 曾了解过线程池却一直模模糊糊的人
  • 了解得差不多却对某些点依然疑惑的

不适合:

  • 完全没看过的,建议你先去看看其他基础文章
  • 看过,却忘得差不多了,建议你先去回顾下

本文能给你的阅读回报

  • 适合的读者,尽可能让你彻底明白常用的线程池的知识相关点
  • 不适合的读者,能有个不错的概念,神童另谈

废话少说,我们开始。下图,皆可自行保存,常常阅之。日久,根深蒂固

默认构造函数

public ThreadPoolExecutor(
    int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler
) 
{
    ....
}

绝对易懂的构造方法参数讲解

参数名

作用

corePoolSize

队列没满时,线程最大并发数

maximumPoolSizes

队列满后线程能够达到的最大并发数

keepAliveTime

空闲线程过多久被回收的时间限制

unit

keepAliveTime 的时间单位

workQueue

阻塞的队列类型

RejectedExecutionHandler

超出 maximumPoolSizes + workQueue 时,任务会交给RejectedExecutionHandler来处理

文字描述

corePoolSize,maximumPoolSize,workQueue之间关系。

  • 当线程池中线程数小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
  • 当线程池中线程数达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 。
  • 当workQueue已满,且maximumPoolSize > corePoolSize时,新提交任务会创建新线程执行任务。
  • 当workQueue已满,且提交任务数超过maximumPoolSize,任务由RejectedExecutionHandler处理。
  • 当线程池中线程数超过corePoolSize,且超过这部分的空闲时间达到keepAliveTime时,回收这些线程。
  • 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize范围内的线程空闲时间达到keepAliveTime也将回收。

一般流程图

newFixedThreadPool 流程图

public static ExecutorService newFixedThreadPool(int nThreads){
    return new ThreadPoolExecutor(
            nThreads,   // corePoolSize
            nThreads,   // maximumPoolSize == corePoolSize
            0L,         // 空闲时间限制是 0
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>() // 无界阻塞队列
        );
}

newCacheThreadPool 流程图

public static ExecutorService newCachedThreadPool(){
    return new ThreadPoolExecutor(
        0,                  // corePoolSoze == 0
        Integer.MAX_VALUE,  // maximumPoolSize 非常大
        60L,                // 空闲判定是60 秒
        TimeUnit.SECONDS,
        // 神奇的无存储空间阻塞队列,每个 put 必须要等待一个 take
        new SynchronousQueue<Runnable>()  
    );
}

newSingleThreadPool 流程图

public static ExecutorService newSingleThreadExecutor() {
        return 
            new FinalizableDelegatedExecutorService
                (
                    new ThreadPoolExecutor
                        (
                            1,
                            1,
                            0L,
                            TimeUnit.MILLISECONDS,
                            new LinkedBlockingQueue<Runnable>(),
                            threadFactory
                        )
                );
    }

可以看到除了多了个 FinalizableDelegatedExecutorService 代理,其初始化和 newFiexdThreadPool 的 nThreads = 1 的时候是一样的。 区别就在于:

  • newSingleThreadExecutor返回的ExcutorService在析构函数finalize()处会调用shutdown()
  • 如果我们没有对它调用shutdown(),那么可以确保它在被回收时调用shutdown()来终止线程。

使用ThreadFactory,可以改变线程的名称、线程组、优先级、守护进程状态,一般采用默认。

流程图略,请参考 newFiexdThreadPool,这里不再累赘。

最后

还有一个定时任务线程池ScheduledThreadPool

它用来处理延时或定时任务,不常用

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT笔记

SpringBoot开发案例之多任务并行+线程池处理

前几篇文章着重介绍了后端服务数据库和多线程并行处理优化,并示例了改造前后的伪代码逻辑。当然了,优化是无止境的,前人栽树后人乘凉。作为我们开发者来说,既然站在了巨...

1.8K190
来自专栏禹都一只猫博客

Linux 性能检测常用的 10 个基本命令

19020
来自专栏码匠的流水账

聊聊hikari连接池的fixed pool design

HikariCP-2.7.6-sources.jar!/com/zaxxer/hikari/pool/HikariPool.java

16030
来自专栏Java开发者杂谈

RocketMQ专题1:入门

​ 这里以RocketMQ的4.3.0版本为例,本地环境为windows10,jdk1.8, maven3.2.1.

44120
来自专栏chenssy

【死磕Java并发】-----J.U.C之线程池:ThreadPoolExecutor

原文出处http://cmsblogs.com/ 『chenssy』 作为Executor框架中最核心的类,ThreadPoolExecutor代表着鼎鼎大名的...

46250
来自专栏猿天地

spring data mongodb 代码连接数据库方式

平时我们用spring data mongodb都是采用xml配置的方式来链接数据库 但是往往有的时候需要用代码的方式来实现。 比如说我们有可能要同时操作多个d...

381140
来自专栏拭心的安卓进阶之路

Android 性能优化:使用 Lint 优化代码、去除多余资源

*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 前言 在保证代码没有功能问题,完成业务开发之余,有追求的程序员还要追求代码的规范、可维护性...

59260
来自专栏Android随笔

利用无障碍服务(AccessibilityService)批量清理后台进程

Demo地址:https://github.com/qyxxjd/ClearProcesses

14510
来自专栏高爽的专栏

再聊线程池

引言 最近恰好在组内分享线程池,又看了看四年前自己写的线程池文章,一是感叹时光荏苒,二是感叹当时的理解太浅薄了,三是感叹自己这么多年依然停留在浅薄的理解当中,没...

26600
来自专栏Golang语言社区

Golang语言-获取命令行参数

/** * Created with IntelliJ IDEA. * User: liaojie * Date: 12-9-8 * Time: 下午3...

363120

扫码关注云+社区

领取腾讯云代金券