diff --git a/README.md b/README.md index 02606fa895c..5f9935aae30 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ * **[Java 并发进阶常见面试题总结](docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md)** * [并发容器总结](docs/java/Multithread/并发容器总结.md) * **[Java线程池学习总结](./docs/java/Multithread/java线程池学习总结.md)** +* [(待办)如何确定线程池线程数量?]() * [乐观锁与悲观锁](docs/essential-content-for-interview/面试必备之乐观锁与悲观锁.md) * [JUC 中的 Atomic 原子类总结](docs/java/Multithread/Atomic.md) @@ -119,7 +120,7 @@ ### 优雅 Java 代码必备实践(Java编程规范) -* [Java 编程规范以及优雅Java代码实践总结](docs/java/Java编程规范.md) +* [Java 编程规范以及优雅 Java 代码实践总结](docs/java/Java编程规范.md) ## 网络 diff --git a/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md b/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md index a70fd5cf159..2fba760bb06 100644 --- a/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md +++ b/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md @@ -450,6 +450,67 @@ public interface Callable { 对应Executors工具类中的方法如图所示: ![Executor框架的工具类](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/Executor框架的工具类.png) +### 4.5 ThreadPoolExecutor 类分析 + +`ThreadPoolExecutor` 类中提供的四个构造方法。我们来看最长的那个,其余三个都是在这个构造方法的基础上产生(其他几个构造方法说白点都是给定某些默认参数的构造方法比如默认制定拒绝策略是什么),这里就不贴代码讲了,比较简单。 + +```java + /** + * 用给定的初始参数创建一个新的ThreadPoolExecutor。 + */ + public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory, + RejectedExecutionHandler handler) { + if (corePoolSize < 0 || + maximumPoolSize <= 0 || + maximumPoolSize < corePoolSize || + keepAliveTime < 0) + throw new IllegalArgumentException(); + if (workQueue == null || threadFactory == null || handler == null) + throw new NullPointerException(); + this.corePoolSize = corePoolSize; + this.maximumPoolSize = maximumPoolSize; + this.workQueue = workQueue; + this.keepAliveTime = unit.toNanos(keepAliveTime); + this.threadFactory = threadFactory; + this.handler = handler; + } +``` + +**下面这些对创建 非常重要,在后面使用线程池的过程中你一定会用到!所以,务必拿着小本本记清楚。** + +#### 4.5.1 `ThreadPoolExecutor`构造函数重要参数分析 + +**`ThreadPoolExecutor` 3 个最重要的参数:** + +- **`corePoolSize` :** 核心线程数线程数定义了最小可以同时运行的线程数量。 +- **`maximumPoolSize` :** 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。 +- **`workQueue`:** 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,信任就会被存放在队列中。 + +`ThreadPoolExecutor`其他常见参数: + +1. **`keepAliveTime`**:当线程池中的线程数量大于 `corePoolSize` 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 `keepAliveTime`才会被回收销毁; +2. **`unit`** : `keepAliveTime` 参数的时间单位。 +3. **`threadFactory`** :executor 创建新线程的时候会用到。 +4. **`handler`** :饱和策略。关于饱和策略下面单独介绍一下。 + +#### 4.5.2 `ThreadPoolExecutor` 饱和策略 + +**`ThreadPoolExecutor` 饱和策略定义:** + +如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任时,`ThreadPoolTaskExecutor` 定义一些策略: + +- **`ThreadPoolExecutor.AbortPolicy`**:抛出 `RejectedExecutionException`来拒绝新任务的处理。 +- **`ThreadPoolExecutor.CallerRunsPolicy`**:调用执行自己的线程运行任务。您不会任务请求。但是这种策略会降低对于新任务提交速度,影响程序的整体性能。另外,这个策略喜欢增加队列容量。如果您的应用程序可以承受此延迟并且你不能任务丢弃任何一个任务请求的话,你可以选择这个策略。 +- **`ThreadPoolExecutor.DiscardPolicy`:** 不处理新任务,直接丢弃掉。 +- **`ThreadPoolExecutor.DiscardOldestPolicy`:** 此策略将丢弃最早的未处理的任务请求。 + +举个例子: Spring 通过 `ThreadPoolTaskExecutor` 或者我们直接通过 `ThreadPoolExecutor` 的构造函数创建线程池的时候,当我们不指定 `RejectedExecutionHandler` 饱和策略的话来配置线程池的时候默认使用的是 `ThreadPoolExecutor.AbortPolicy`。在默认情况下,`ThreadPoolExecutor` 将抛出 `RejectedExecutionException` 来拒绝新来的任务 ,这代表你将丢失对这个任务的处理。 对于可伸缩的应用程序,建议使用 `ThreadPoolExecutor.CallerRunsPolicy`。当最大池被填满时,此策略为我们提供可伸缩队列。(这个直接查看 `ThreadPoolExecutor` 的构造函数源码就可以看出,比较简单的原因,这里就不贴代码了。) + ## 5. Atomic 原子类 ### 5.1. 介绍一下Atomic 原子类 diff --git "a/docs/java/Multithread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/java/Multithread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" index a172bbc486e..7aa9fe420bb 100644 --- "a/docs/java/Multithread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" +++ "b/docs/java/Multithread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" @@ -197,8 +197,6 @@ public class ScheduledThreadPoolExecutor 对应 Executors 工具类中的方法如图所示: ![通过Executor 框架的工具类Executors来实现](https://imgconvert.csdnimg.cn/aHR0cDovL215LWJsb2ctdG8tdXNlLm9zcy1jbi1iZWlqaW5nLmFsaXl1bmNzLmNvbS8xOC00LTE2LzEzMjk2OTAxLmpwZw?x-oss-process=image/format,png) - - ## 四 (重要)ThreadPoolExecutor 使用示例 我们上面讲解了 `Executor`框架以及 `ThreadPoolExecutor` 类,下面让我们实战一下,来通过写一个 `ThreadPoolExecutor` 的小 Demo 来回顾上面的内容。 @@ -550,8 +548,6 @@ Wed Nov 13 13:40:43 CST 2019::pool-1-thread-4 Wed Nov 13 13:40:43 CST 2019::pool-1-thread-5 ``` - - ##五 几种常见的线程池详解 ### 5.1 FixedThreadPool