ThreadPoolExecutor运作流程

本文详细解析了ThreadPoolExecutor的工作原理及参数设置,介绍了其内部结构和线程管理方式,并通过几个特殊线程池的例子展示了不同场景下的应用。

ThreadPoolExecutor运作流程 

转载自:http://blog.youkuaiyun.com/cutesource/article/details/6061229

最近发现几起对ThreadPoolExecutor的误用,其中包括自己,发现都是因为没有仔细看注释和内部运转机制,想当然的揣测参数导致,先看一下新建一个ThreadPoolExecutor的构建参数:

[java]  view plain  copy
print ?
  1. public ThreadPoolExecutor(int corePoolSize,  
  2.                           int maximumPoolSize,  
  3.                           long keepAliveTime,  
  4.                           TimeUnit unit,  
  5.                           BlockingQueue<Runnable> workQueue,  
  6.                           ThreadFactory threadFactory,  
  7.                           RejectedExecutionHandler handler)  
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

看这个参数很容易让人以为是线程池里保持corePoolSize个线程,如果不够用,就加线程入池直至maximumPoolSize大小,如果还不够就往workQueue里加,如果workQueue也不够就用RejectedExecutionHandler来做拒绝处理。

但实际情况不是这样,具体流程如下:

1)当池子大小小于corePoolSize就新建线程,并处理请求

2)当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去从workQueue中取任务并处理

3)当workQueue放不下新入的任务时,新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize就用RejectedExecutionHandler来做拒绝处理

4)另外,当池子的线程数大于corePoolSize的时候,多余的线程会等待keepAliveTime长的时间,如果无请求可处理就自行销毁

内部结构如下所示:

从中可以发现ThreadPoolExecutor就是依靠BlockingQueue的阻塞机制来维持线程池,当池子里的线程无事可干的时候就通过workQueue.take()阻塞住。

其实可以通过Executes来学学几种特殊的ThreadPoolExecutor是如何构建的。

[java]  view plain  copy
print ?
  1. public static ExecutorService newFixedThreadPool(int nThreads) {  
  2.     return new ThreadPoolExecutor(nThreads, nThreads,  
  3.                                   0L, TimeUnit.MILLISECONDS,  
  4.                                   new LinkedBlockingQueue<Runnable>());  
  5. }  
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }

newFixedThreadPool就是一个固定大小的ThreadPool

[java]  view plain  copy
print ?
  1. public static ExecutorService newCachedThreadPool() {  
  2.     return new ThreadPoolExecutor(0, Integer.MAX_VALUE,  
  3.                                   60L, TimeUnit.SECONDS,  
  4.                                   new SynchronousQueue<Runnable>());  
  5. }  
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }

newCachedThreadPool比较适合没有固定大小并且比较快速就能完成的小任务,没必要维持一个Pool,这比直接new Thread来处理的好处是能在60秒内重用已创建的线程。

其他类型的ThreadPool看看构建参数再结合上面所说的特性就大致知道它的特性

### Java线程池执行流程及相关解释 Java中的线程池通过`ThreadPoolExecutor`类实现,其工作流程可以分为以下几个部分: #### 1. **线程池初始化** 线程池在创建时需要指定多个参数来定义它的行为模式。这些参数包括但不限于核心线程数(`corePoolSize`)、最大线程数(`maximumPoolSize`)、空闲线程存活时间(`keepAliveTime`)等[^1]。 #### 2. **任务提交阶段** 当一个任务被提交到线程池时,线程池会按照以下顺序决定如何处理该任务: - 如果当前运行的线程数量小于`corePoolSize`,则优先创建新的线程来执行新提交的任务。 - 若当前线程数已达到`corePoolSize`,则将任务放入阻塞队列中等待执行。 - 当阻塞队列也满了之后,如果此时线程总数仍低于`maximumPoolSize`,则继续创建新线程直到达到上限。 - 假设以上条件均不满足(即线程已达最大值且队列满),那么将会触发拒绝策略来应对无法处理的新任务[^5]。 #### 3. **任务执行与管理** 一旦某个线程从队列获取到了一个待办事项并开始运作,在此期间它不会轻易返回给闲置状态除非特定情况发生比如超出了设定的时间长度或者接收到停止信号等情况。另外值得注意的是对于设置了允许核心线程超时期限属性的情况而言即使处于忙碌之中只要超过了规定时限同样会被销毁从而减少不必要的资源消耗[^2]。 #### 4. **线程池关闭过程** 在线程池进入关闭状态之前可能经历两种不同的操作方式:一种是由开发者主动调用诸如 `shutdown()` 或者更激进版本的方法如 `shutdownNow()` 来发起;另一种则是由于外部因素影响致使整个应用环境发生变化进而间接促使内部机制响应做出相应调整动作。无论哪种情形下都会涉及到对现存工作者对象列表逐一排查确认哪些应该保留哪些需被淘汰出局等问题,并最终达成完全退出目标[^4]。 以下是几种常见的固定大小类型的线程池及其特点概述图解说明如下所示: - Fixed Thread Pool: ![newFixedThreadPool](https://example.com/newFixedThreadPool.png) - Cached Thread Pool: ![newCachedThreadPool](https://example.com/newCachedThreadPool.png) - Single Thread Executor: ![newSingleThreadExecutor](https://example.com/newSingleThreadExecutor.png) ```java public class ThreadPoolExample { public static void main(String[] args) { // 创建具有三个核心线程的线程池实例 ThreadPoolExecutor executor = new ThreadPoolExecutor( 3, // corePoolSize 5, // maximumPoolSize 60L, // keepAliveTime TimeUnit.SECONDS, new LinkedBlockingQueue<>() ); for (int i = 0; i < 10; ++i) { int taskId = i; executor.execute(() -> System.out.println("Executing Task " + taskId)); } executor.shutdown(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值