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,外包线程是否已经满了,如果没有,创建一个线程执行,否则按照策略处理无法执行的任务
转载于:https://my.oschina.net/lovexin/blog/1795807