04-并发编程之Java线程池底层原理分析

1. 线程池定义

一个管理线程的池子或容器,是一种基于池化思想管理线程的工具。线程池的作用是管理线程、减少线程对象创建和销毁的性能开销。

2. 原理解析

2.1 七大核心参数

  1. corePoolSize                           核心线程数
  2. maximumPoolSize                   最大线程数
  3. keepAliveTime                         任务结束后线程的存活时间
  4. TimeUnit                                  keepAliveTime的单位,常用s,ms
  5. BlockingQueue                        任务缓冲队列
  6. ThreadFactory                         线程工厂
  7. 拒绝策略                                  默认AbortPolicy,直接丢弃,并抛出异常

2.2 线程池的运行原理

线程池的任务调度都是由execute/submit方法完成的,在这个过程中,要检查线程池的运行状态、工作线程数、任务队列以及拒绝策略等,以决定接下来的执行流程是直接执行,还是缓冲执行,亦或是拒绝任务。其执行流程如下:

  1. 首先对线程数进行判断,如果工作线程数小于核心线程数,直接创建一个核心工作线程执行任务,否则尝试将任务添加到工作队列
  2. 如果添加队列成功,判断一下工作线程数是否小于最大线程数maximumPoolSize,如果是就创建一个非核心工作线程执行任务,否则直接退出;
  3. 如果添加队列失败,尝试直接创建一个非核心工作线程执行任务,创建失败则交给拒绝策略来处理这个任务;
  4. 当一个线程完成任务的时候,它会从缓冲队列中取下一个任务来执行;
  5. 当一个线程空闲超过一定时间(keepAliveTime)时,线程池进行会判断:如果当前的工作线程数大于核心线程数corePoolSize,那么这个线程就会被终止。

 

3. 线程池的使用

3.1 JDK提供的几种创建线程池的方式

Executors 是JDK1.5开始提供的一个线程池工具类,支持直接调用方法创建不同的线程池,它们分别是:

1. Executors.newCacheThreadPool()

创建一个缓存线程池,可缓存线程以便重复使用。任务缓冲队列为SynchronousQueue,其容量为0,存取数据都要阻塞,来一个任务就创建一个工作线程执行任务;

2. Executors.newFixedThreadPool(10)

创建一个数量固定的线程池。任务缓冲队列为LinkedBlockingQueue,队列最大长度Integer.MAX_VALUE,使用不当会出现OOM问题。

3. Executors.newSingleThreadExecutor()

创建单个线程的线程池。由于只有一个线程,所以会不断复用,无法完全发挥CPU的性能,更适用于IO密集型任务。任务缓冲队列也是LinkedBlockingQueue。

4. Executors.newScheduledThreadPool(10)

创建一个定时周期性执行任务的线程池。任务缓冲队列使用延迟队列DelayedWorkQueue,特点是按照延迟时间的长短来排序,即下一个执行的任务排在最前面。

5. newSingleThreadScheduledExecutor()
单线程的定时任务线程池,相当于newScheduledThreadPool(1);

6. newWorkStealingPool()

工作窃取线程池。Java8新增的创建线程池的方法,此线程池会并行处理任务,不能保证执行顺序,底层采用ForkJoinPool实现。

(阿里巴巴)不建议通过Executors 线程池去创建线程池,尤其是CachedThreadPool、FixedThreadPool和SingleThreadExecutor,因为CachedThreadPool的任务队列SynchronousQueue使用CAS自旋的方式保证线程安全,高并发下回产生大量CAS冲突自旋,发生CPU100%问题;FixedThreadPool和SingleThreadExecutor的任务队列默认长度为Integer.MAX_VALUE,可能会堆积大量的任务,从而导致 OOM。

3.2 线程池的4种拒绝策略

  • AbortPolicy,抛出异常RejectedExecutionException拒绝提交任务;
  • DiscardPolicy,直接抛弃任务,不做任何处理;
  • DiscardOldestPolicy,去除任务队列中的第一个任务(最旧的),重新提交;
  • CallerRunsPolicy,由调用execute方法提交任务的线程来执行这个任务;

 3.3 线程池的生命周期

  • running:线程池在运行,可添加执行任务,可执行队列任务
  • shutdown:线程池关闭
    • shutdown 平缓关闭:已经启动的任务全部执行完毕,等待队列中的阻塞任务会继续执行,同时不再接受新的任务 
    • shutdowNow 立即关闭:取消所有正在执行和未执行的任务(等同于stop)
  • stop:线程池停止完毕,所有任务都已停止执行
  • tidying:线程池整理,为接下来的终止做准备
  • terminated:线程池终止,彻底关闭

3.4 线程池的继承结构

Executor和ExecutorService提供的方法 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值