ThreadPoolExecutor线程池源码笔记

1.使用线程池的目的:

和数据库连接池类似,防止频繁创建与销毁对象造成的系统开销(GC回收与对象初始化都是一个比较耗时的操作)

2.创建线程池的方式(官方不推荐直接new的方式,而是Executors类提供的静态方式工具类创建)

共有五种:

    A)Executors.newCachedThreadPool();

    B)Executors.newSingleThreadExecutor();

    C)Executors.newSingleThreadScheduledExecutor();

    D)Executors.newScheduledThreadPool();

    E)Executors.newFixedThreadPool();

    那么这五种方式的各自什么特点呢?

        首先、这里先介绍一下线程池初始化构造函数及其所有参数的各自含义:

        

    以上为线程池的构造函数,这里解释一下参数的具体意义:

        corePoolSize:核心线程,相当于公司开发人员中的内部成员,处理具体请求,内部员工之外为外包人员(内部人员+外包人员 <= 总工位数)

        maximumPoolSize:最大的线程数量,相当于公司开发场地的工位数量,

        keepAliveTime:空闲时间,相当于需求完毕之后,多久接不到活需要将外包人员派遣回原公司

        workQueue:阻塞队列,相当于需求

        handler:如果请求数量大于最大线程数,阻塞队列被占满之后的处理拦截器;相当于需求来的太多,内部人员和外包人员怎么处理都非常吃力,已经没有时间再处理新的需求时,对这些需求的方式

理解这几个参数之后,咱们回归上面问题 “那么这五种方式的各自什么特点呢?”

2.1 newCachedThreadPool

    源码:

    特点:

        A)从图上可以看出,核心线程数为0,核心外线程数为Integer的最大值,此种情况会提高执行许多短期异步任务的程序的性能,空闲时间足够长的池不会消耗任何资源;

        B)使用的是SynchronousQueue,该队列线程池中较为常用,特点为不存储任何数据,只做为转发的形式,类似于中转站

2.2 newSingleThreadExecutor

    源码:

说明:FinalizableDelegatedExecutorService为Executors中的子类,最终执行还是ThreadPoolExecutor类

    特点:

        A)只有一个核心线程(但是请注意,如果这个单线程在关闭前执行失败,那么在执行后续任务时需要一个新的线程。)

        B)队列没有边界,所有请求都是按照顺序执行,并且在任何给定的时间内都不会有一个任务处于活动状态

2.3 newSingleThreadScheduledExecutor

    源码:

    特点:

        A)和newSingleThreadExecutor一样,只有一个核心线程,但是外包线程几乎无限制,且不能有外包线程

        B)该线程池可以在给定延迟后调度命令运行,或定期执行命令,但是请注意,如果单线程在关闭前在执行过程中失败,那么如果需要执行,则新线程将取代它。

2.4 newScheduledThreadPool

    源码:

    特点:

        A)核心线程数由用户自定义设置,但是外包线程几乎无限制,且不能有外包线程

        B)该线程池可以在给定延迟后调度命令运行,或定期执行命令。

2.5 newFixedThreadPool

    源码:

    特点:

        A)没有外包线程,由用户提供核心线程数和总线程数

        B)队列使用的是无界队列

3. 执行流程

    源码:

    

    流程:

        画图版(盗的某大佬的图):

这里写图片描述

        文字版:

    1,获取现在工作的线程数量,如果比核心线程小,直接添加到核心线程池中,并且立即执行,否则执行第二步

    2,队列是否已经满了,如果没有,讲任务添加到队列中,如果已经满了,执行第三步

    3,外包线程是否已经满了,如果没有,创建一个线程执行,否则按照策略处理无法执行的任务

    

猜你喜欢

转载自my.oschina.net/lovexin/blog/1795807