1. 线程池使用方式
示例代码:
// 一池N线程
Executors.newFixedThreadPool(int)
// 一个任务一个任务执行,一池一线程
Executors.newSingleThreadExecutorO
// 线程池根据需求创建线程,可扩容,遇强则强
Executors.newCachedThreadPool()
// 自定义线程池方式
new ThreadPoolExecutor(...)
注:一般在工作中都是根据业务场景进行自定义线程池,进行使用;
自定义线程池方法;详见后面章节:自定义线程池
2. 线程池底层工作原理
a. 线程池参数:
线程池,具有多个参数:具有各自的含义:
七参数:
- corePoolSize:核心线程数,一直保持活跃状态的线程
- maximumPoolSize:最大线程数,线程池能容纳的最大线程数量
- keepAliveTime:空闲线程存活时间,非核心线程的空闲存活时间
- unit:存活的时间单位,非核心线程的空闲存活时间单位
- workQueue:存放未执行任务的队列
- threadFactory:线程工厂,创建线程的工厂类
- handler:拒绝策略,队列满了和达到最大线程数后的拒绝策略
如图:
b. 线程池的拒绝策略
AbortPolicy:默认,直接抛出RejectedExcutionException异常,阻止系统正常运行
CallerRunsPolicy:该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者
DiscardPolicy:直接丢弃任务,不予任何处理也不抛出异常,如果允许任务丢失,这是一种好方案
DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务
c. 线程池底层工作原理
-
在创建了线程池后,如果设置了核心线程数(corePoolSize),则线程池中的线程数会先创建相应数量的核心线程。如果没有任务到达,这些核心线程会保持活动状态。
-
当调用execute()方法添加一个请求任务时,线程池会根据以下判断来决定任务的执行方式:
- 如果正在运行的线程数量小于核心线程数(corePoolSize),则会立即使用核心线程来执行任务。
- 如果正在运行的线程数量大于或等于核心线程数,但任务队列未满,则任务会被放入队列中等待执行。
- 如果队列已满且正在运行的线程数量小于最大线程数(maximumPoolSize),则会创建非核心线程来执行任务。
- 这里需要注意,是先执行新的任务,队列里的任务不会执行,详见:5. 注意事项
- 如果队列已满且正在运行的线程数量已达到最大线程数,且拒绝策略允许,那么线程池会启动拒绝策略来处理新任务。
-
当一个线程完成任务时,它会从队列中取下一个任务来执行,或者在没有任务的情况下进入等待状态。
-
当一个线程空闲时间超过设定的keepAliveTime时,线程池会根据以下判断来决定线程的命运:
- 如果当前运行的线程数大于核心线程数(corePoolSize),则空闲线程会被终止。
- 线程池的所有任务完成后,它最终会收缩到核心线程数的大小。
-
注意事项:
在Java中java.util.concurrent.ThreadPoolExecutor线程池的默认行为是,当任务队列已满且再来一个新任务时,创建的新线程会被用来执行新来的任务而不是队列里已有的任务。
-
线程工作原理示意图:
3. 自定义线程池
a. 介绍:
前面提到过,一般在工作中都是根据业务场景进行自定义线程池;西面是阿里巴巴开发手册的说明;
b. 实现:
…待续。
标签:自定义,队列,核心,ThreadPool,任务,线程,原理,执行 From: https://blog.csdn.net/m0_72560900/article/details/137080602