1- Java 面试通关手册(Java 学习指南,欢迎 Star,会一直完善下去,欢迎建议和指导):[ https://github.com/Snailclimb/Java_Guide ] ( https://github.com/Snailclimb/Java_Guide " https://github.com/Snailclimb/Java_Guide ")
1+ <!-- TOC -->
2+ 3+ - [ 一 使用线程池的好处] ( #一-使用线程池的好处 )
4+ - [ 二 Executor 框架] ( #二-executor-框架 )
5+ - [ 2.1 简介] ( #21-简介 )
6+ - [ 2.2 Executor 框架结构(主要由三大部分组成)] ( #22-executor-框架结构主要由三大部分组成 )
7+ - [ 1 任务。] ( #1-任务 )
8+ - [ 2 任务的执行] ( #2-任务的执行 )
9+ - [ 3 异步计算的结果] ( #3-异步计算的结果 )
10+ - [ 2.3 Executor 框架的使用示意图] ( #23-executor-框架的使用示意图 )
11+ - [ 三 ThreadPoolExecutor 类简单介绍(重要)] ( #三-threadpoolexecutor-类简单介绍重要 )
12+ - [ 3.1 ThreadPoolExecutor 类分析] ( #31-threadpoolexecutor-类分析 )
13+ - [ 3.2 推荐使用ThreadPoolExecutor 构造函数创建线程池] ( #32-推荐使用threadpoolexecutor-构造函数创建线程池 )
14+ - [ 四 ThreadPoolExecutor 使用示例] ( #四-threadpoolexecutor-使用示例 )
15+ - [ 4.1 示例代码] ( #41-示例代码 )
16+ - [ 4.2 原理分析] ( #42-原理分析 )
17+ - [ 4.3 几个常见的方法对比] ( #43-几个常见的方法对比 )
18+ - [ 4.3.1 shutdown()VS shutdownNow()] ( #431-shutdownvs-shutdownnow )
19+ - [ 4.3.2 isTerminated() Vs isShutdown()] ( #432-isterminated-vs-isshutdown )
20+ - [ 五 几种常见的线程池详解] ( #五-几种常见的线程池详解 )
21+ - [ 5.1 FixedThreadPool 详解] ( #51-fixedthreadpool-详解 )
22+ - [ 5.2 SingleThreadExecutor 详解] ( #52-singlethreadexecutor-详解 )
23+ - [ 5.3 CachedThreadPool 详解] ( #53-cachedthreadpool-详解 )
24+ - [ 六 ScheduledThreadPoolExecutor 详解] ( #六-scheduledthreadpoolexecutor-详解 )
25+ - [ 6.1 简介] ( #61-简介 )
26+ - [ 6.2 运行机制] ( #62-运行机制 )
27+ - [ 6.3 ScheduledThreadPoolExecutor 执行周期任务的步骤] ( #63-scheduledthreadpoolexecutor-执行周期任务的步骤 )
28+ - [ 6.4 ScheduledThreadPoolExecutor 使用示例] ( #64-scheduledthreadpoolexecutor-使用示例 )
29+ - [ 6.4.1 ScheduledExecutorService scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)方法] ( #641-scheduledexecutorservice-scheduleatfixedraterunnable-commandlong-initialdelaylong-periodtimeunit-unit方法 )
30+ - [ 6.4.2 ScheduledExecutorService scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)方法] ( #642-scheduledexecutorservice-schedulewithfixeddelayrunnable-commandlong-initialdelaylong-delaytimeunit-unit方法 )
31+ - [ 6.4.3 scheduleWithFixedDelay() vs scheduleAtFixedRate()] ( #643-schedulewithfixeddelay-vs-scheduleatfixedrate )
32+ - [ 七 各种线程池的适用场景介绍] ( #七-各种线程池的适用场景介绍 )
33+ - [ 八 总结] ( #八-总结 )
34+ - [ 九 参考] ( #九-参考 )
35+ - [ 十 其他推荐阅读] ( #十-其他推荐阅读 )
36+ 37+ <!-- /TOC -->
238
339## 一 使用线程池的好处
440
@@ -181,11 +217,11 @@ public class ScheduledThreadPoolExecutor
181217对应 Executors 工具类中的方法如图所示:
182218![ 通过Executor 框架的工具类Executors来实现] ( https://imgconvert.csdnimg.cn/aHR0cDovL215LWJsb2ctdG8tdXNlLm9zcy1jbi1iZWlqaW5nLmFsaXl1bmNzLmNvbS8xOC00LTE2LzEzMjk2OTAxLmpwZw?x-oss-process=image/format,png )
183219
184- ## 五 ThreadPoolExecutor 使用示例
220+ ## 四 ThreadPoolExecutor 使用示例
185221
186222我们上面讲解了 ` Executor ` 框架以及 ` ThreadPoolExecutor ` 类,下面让我们实战一下,来通过写一个 ` ThreadPoolExecutor ` 的小 Demo 来回顾上面的内容。
187223
188- ### 5 .1 示例代码
224+ ### 4 .1 示例代码
189225
190226首先创建一个 ` Runnable ` 接口的实现类(当然也可以是 ` Callable ` 接口,我们上面也说了两者的区别是:` Runnable ` 接口不会返回结果但是 ` Callable ` 接口可以返回结果。后面介绍 ` Executors ` 类的一些方法的时候会介绍到两者的相互转换。)
191227
@@ -300,7 +336,7 @@ pool-1-thread-1 End. Time = Tue Nov 12 20:59:54 CST 2019
300336
301337```
302338
303- ### 5 .2 原理分析
339+ ### 4 .2 原理分析
304340
305341承接 5.1 节,我们通过代码输出结果可以看出:** 线程池每次会同时执行 5 个任务,这5 个任务执行完之后,剩余的 5 个任务才会被执行。** 大家可以先通过上面讲解的内容,分析一下到底是咋回事?(自己独立思考一会)
306342
@@ -361,21 +397,21 @@ pool-1-thread-1 End. Time = Tue Nov 12 20:59:54 CST 2019
361397
362398> 我们在代码中模拟了 10 个任务,我们配置的核心线程数为 5 、等待队列容量为 100 ,所以每次只可能存在 5 个任务同时执行,剩下的 5 个任务会被放到等待队列中去。当前的 5 个任务之行完成后,才会之行剩下的 5 个任务。
363399
364- ### 5 .3 几个常见的方法对比
400+ ### 4 .3 几个常见的方法对比
365401
366- #### 5 .3.1 shutdown()VS shutdownNow()
402+ #### 4 .3.1 shutdown()VS shutdownNow()
367403
368404- ** ` shutdown() ` ** :关闭线程池,线程池的状态变为 ` SHUTDOWN ` 。线程池不再接受新任务了,但是队列里的任务得执行完毕。
369405- ** ` shutdownNow() ` ** :关闭线程池,线程的状态变为 ` STOP ` 。线程池会终止当前正在运行的任务,并停止处理排队的任务并返回正在等待执行的 List。
370406
371- #### 5 .3.2 isTerminated() Vs isShutdown()
407+ #### 4 .3.2 isTerminated() Vs isShutdown()
372408
373409- ** ` isShutDown ` ** 当调用 ` shutdown() ` 方法后返回为true。
374410- ** ` isTerminated ` ** 当调用 ` shutdown() ` 方法后,并且所有提交的任务完成后返回为true
375411
376- ##四 几种常见的线程池详解
412+ ##五 几种常见的线程池详解
377413
378- ### 4 .1 FixedThreadPool 详解
414+ ### 5 .1 FixedThreadPool 详解
379415
380416` FixedThreadPool ` 被称为可重用固定线程数的线程池。通过 Executors 类中的相关源代码来看一下相关实现:
381417
@@ -419,7 +455,7 @@ pool-1-thread-1 End. Time = Tue Nov 12 20:59:54 CST 2019
4194553 . 由于 1 和 2,使用无界队列时 keepAliveTime 将是一个无效参数;
4204564 . 运行中的 FixedThreadPool(未执行 shutdown()或 shutdownNow()方法)不会拒绝任务
421457
422- ### 3.5 SingleThreadExecutor 详解
458+ ### 5.2 SingleThreadExecutor 详解
423459
424460SingleThreadExecutor 是使用单个 worker 线程的 Executor。下面看看** SingleThreadExecutor 的实现:**
425461
@@ -462,7 +498,7 @@ SingleThreadExecutor 是使用单个 worker 线程的 Executor。下面看看**S
4624982 . 当前线程池中有一个运行的线程后,将任务加入 LinkedBlockingQueue
4634993 . 线程执行完 1 中的任务后,会在循环中反复从 LinkedBlockingQueue 中获取任务来执行;
464500
465- ### 3.6 CachedThreadPool 详解
501+ ### 5.3 CachedThreadPool 详解
466502
467503CachedThreadPool 是一个会根据需要创建新线程的线程池。下面通过源码来看看 CachedThreadPool 的实现:
468504
@@ -501,31 +537,31 @@ CachedThreadPool 的 corePoolSize 被设置为空(0),maximumPoolSize 被
5015371 . 首先执行 SynchronousQueue.offer(Runnable task)。如果当前 maximumPool 中有闲线程正在执行 SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS),那么主线程执行 offer 操作与空闲线程执行的 poll 操作配对成功,主线程把任务交给空闲线程执行,execute()方法执行完成,否则执行下面的步骤 2;
5025382 . 当初始 maximumPool 为空,或者 maximumPool 中没有空闲线程时,将没有线程执行 SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS)。这种情况下,步骤 1 将失败,此时 CachedThreadPool 会创建新线程执行任务,execute 方法执行完成;
503539
504- ## 四 ScheduledThreadPoolExecutor 详解
540+ ## 六 ScheduledThreadPoolExecutor 详解
505541
506- ### 4 .1 简介
542+ ### 6 .1 简介
507543
508- ** ScheduledThreadPoolExecutor 主要用来在给定的延迟后运行任务,或者定期执行任务。**
544+ ** ` ScheduledThreadPoolExecutor ` 主要用来在给定的延迟后运行任务,或者定期执行任务。**
509545
510- ** ScheduledThreadPoolExecutor 使用的任务队列 DelayQueue 封装了一个 PriorityQueue, PriorityQueue 会对队列中的任务进行排序,执行所需时间短的放在前面先被执行(ScheduledFutureTask 的 time 变量小的先执行),如果执行所需时间相同则先提交的任务将被先执行(ScheduledFutureTask 的 squenceNumber 变量小的先执行)。**
546+ ** ` ScheduledThreadPoolExecutor ` 使用的任务队列 ` DelayQueue ` 封装了一个 ` PriorityQueue ` , ` PriorityQueue ` 会对队列中的任务进行排序,执行所需时间短的放在前面先被执行(` ScheduledFutureTask ` 的 ` time ` 变量小的先执行),如果执行所需时间相同则先提交的任务将被先执行(` ScheduledFutureTask ` 的 ` squenceNumber ` 变量小的先执行)。**
511547
512- ** ScheduledThreadPoolExecutor 和 Timer 的比较:**
548+ ** ` ScheduledThreadPoolExecutor ` 和 ` Timer ` 的比较:**
513549
514- - Timer 对系统时钟的变化敏感,ScheduledThreadPoolExecutor 不是;
515- - Timer 只有一个执行线程,因此长时间运行的任务可以延迟其他任务。 ScheduledThreadPoolExecutor 可以配置任意数量的线程。 此外,如果你想(通过提供 ThreadFactory),你可以完全控制创建的线程;
516- - 在 TimerTask 中抛出的运行时异常会杀死一个线程,从而导致 Timer 死机:-( ...即计划任务将不再运行。ScheduledThreadExecutor 不仅捕获运行时异常,还允许您在需要时处理它们(通过重写 afterExecute 方法 ThreadPoolExecutor)。抛出异常的任务将被取消,但其他任务将继续运行。
550+ - ` Timer ` 对系统时钟的变化敏感,` ScheduledThreadPoolExecutor ` 不是;
551+ - ` Timer ` 只有一个执行线程,因此长时间运行的任务可以延迟其他任务。 ` ScheduledThreadPoolExecutor ` 可以配置任意数量的线程。 此外,如果你想(通过提供 ThreadFactory),你可以完全控制创建的线程;
552+ - 在` TimerTask ` 中抛出的运行时异常会杀死一个线程,从而导致 ` Timer ` 死机:-( ...即计划任务将不再运行。` ScheduledThreadExecutor ` 不仅捕获运行时异常,还允许您在需要时处理它们(通过重写 ` afterExecute ` 方法` ThreadPoolExecutor ` )。抛出异常的任务将被取消,但其他任务将继续运行。
517553
518554** 综上,在 JDK1.5 之后,你没有理由再使用 Timer 进行任务调度了。**
519555
520556> ** 备注:** Quartz 是一个由 java 编写的任务调度库,由 OpenSymphony 组织开源出来。在实际项目开发中使用 Quartz 的还是居多,比较推荐使用 Quartz。因为 Quartz 理论上能够同时对上万个任务进行调度,拥有丰富的功能特性,包括任务调度、任务持久化、可集群化、插件等等。
521557
522- ### 4.2 ScheduledThreadPoolExecutor 运行机制
558+ ### 6.2 运行机制
523559
524560![ ScheduledThreadPoolExecutor运行机制] ( https://imgconvert.csdnimg.cn/aHR0cDovL215LWJsb2ctdG8tdXNlLm9zcy1jbi1iZWlqaW5nLmFsaXl1bmNzLmNvbS8xOC00LTE2LzkyNTk0Njk4LmpwZw?x-oss-process=image/format,png )
525561
526- ** ScheduledThreadPoolExecutor 的执行主要分为两大部分:**
562+ ** ` ScheduledThreadPoolExecutor ` 的执行主要分为两大部分:**
527563
528- 1 . 当调用 ScheduledThreadPoolExecutor 的 ** scheduleAtFixedRate()** 方法或者** scheduleWirhFixedDelay()** 方法时,会向 ScheduledThreadPoolExecutor 的 ** DelayQueue** 添加一个实现了 ** RunnableScheduledFutur ** 接口的 ** ScheduledFutureTask** 。
564+ 1 . 当调用 ` ScheduledThreadPoolExecutor ` 的 ** ` scheduleAtFixedRate() ` ** 方法或者** ` scheduleWirhFixedDelay() ` ** 方法时,会向 ` ScheduledThreadPoolExecutor ` 的 ** ` DelayQueue ` ** 添加一个实现了 ** ` RunnableScheduledFuture ` ** 接口的 ** ` ScheduledFutureTask ` ** 。
5295652 . 线程池中的线程从 DelayQueue 中获取 ScheduledFutureTask,然后执行任务。
530566
531567** ScheduledThreadPoolExecutor 为了实现周期性的执行任务,对 ThreadPoolExecutor 做了如下修改:**
@@ -534,7 +570,7 @@ CachedThreadPool 的 corePoolSize 被设置为空(0),maximumPoolSize 被
534570- 获取任务的方不同
535571- 执行周期任务后,增加了额外的处理
536572
537- ### 4 .3 ScheduledThreadPoolExecutor 执行周期任务的步骤
573+ ### 6 .3 ScheduledThreadPoolExecutor 执行周期任务的步骤
538574
539575![ ScheduledThreadPoolExecutor执行周期任务的步骤] ( https://imgconvert.csdnimg.cn/aHR0cDovL215LWJsb2ctdG8tdXNlLm9zcy1jbi1iZWlqaW5nLmFsaXl1bmNzLmNvbS8xOC01LTMwLzU5OTE2Mzg5LmpwZw?x-oss-process=image/format,png )
540576
@@ -543,7 +579,7 @@ CachedThreadPool 的 corePoolSize 被设置为空(0),maximumPoolSize 被
5435793 . 线程 1 修改 ScheduledFutureTask 的 time 变量为下次将要被执行的时间;
5445804 . 线程 1 把这个修改 time 之后的 ScheduledFutureTask 放回 DelayQueue 中(DelayQueue.add())。
545581
546- ### 4 .4 ScheduledThreadPoolExecutor 使用示例
582+ ### 6 .4 ScheduledThreadPoolExecutor 使用示例
547583
5485841 . 创建一个简单的实现 Runnable 接口的类(我们上面的例子已经实现过)
549585
@@ -596,7 +632,7 @@ Current Time = Wed May 30 17:11:49 CST 2018
596632Finished all threads
597633```
598634
599- #### 4 .4.1 ScheduledExecutorService scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)方法
635+ #### 6 .4.1 ScheduledExecutorService scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)方法
600636
601637我们可以使用 ScheduledExecutorService scheduleAtFixedRate 方法来安排任务在初始延迟后运行,然后在给定的时间段内运行。
602638
@@ -645,7 +681,7 @@ Process finished with exit code 0
645681
646682```
647683
648- #### 4 .4.2 ScheduledExecutorService scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)方法
684+ #### 6 .4.2 ScheduledExecutorService scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)方法
649685
650686ScheduledExecutorService scheduleWithFixedDelay 方法可用于以初始延迟启动周期性执行,然后以给定延迟执行。 延迟时间是线程完成执行的时间。
651687
@@ -700,15 +736,15 @@ pool-1-thread-2 End. Time = Wed May 30 17:58:46 CST 2018
700736Finished all threads
701737```
702738
703- #### 4 .4.3 scheduleWithFixedDelay() vs scheduleAtFixedRate()
739+ #### 6 .4.3 scheduleWithFixedDelay() vs scheduleAtFixedRate()
704740
705741scheduleAtFixedRate(...)将延迟视为两个任务开始之间的差异(即定期调用)
706742scheduleWithFixedDelay(...)将延迟视为一个任务结束与下一个任务开始之间的差异
707743
708744> ** scheduleAtFixedRate():** 创建并执行在给定的初始延迟之后,随后以给定的时间段首先启用的周期性动作; 那就是执行将在 initialDelay 之后开始,然后 initialDelay+period ,然后是 initialDelay + 2 \* period ,等等。 如果任务的执行遇到异常,则后续的执行被抑制。 否则,任务将仅通过取消或终止执行人终止。 如果任务执行时间比其周期长,则后续执行可能会迟到,但不会同时执行。
709745> ** scheduleWithFixedDelay() :** 创建并执行在给定的初始延迟之后首先启用的定期动作,随后在一个执行的终止和下一个执行的开始之间给定的延迟。 如果任务的执行遇到异常,则后续的执行被抑制。 否则,任务将仅通过取消或终止执行终止。
710746
711- ## 五 各种线程池的适用场景介绍
747+ ## 七 各种线程池的适用场景介绍
712748
713749- ** FixedThreadPool:** 适用于为了满足资源管理需求,而需要限制当前线程数量的应用场景。它适用于负载比较重的服务器;
714750
@@ -720,19 +756,20 @@ scheduleWithFixedDelay(...)将延迟视为一个任务结束与下一个任
720756
721757** SingleThreadScheduledExecutor:** 适用于需要单个后台线程执行周期任务,同时保证顺序地执行各个任务的应用场景。
722758
723- ## 六 总结
759+ ## 八 总结
724760
725761本节只是简单的介绍了一下使用线程池的好处,然后花了大量篇幅介绍 Executor 框架。详细介绍了 Executor 框架中 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor,并且通过实例详细讲解了 ScheduledThreadPoolExecutor 的使用。对于 FutureTask 只是粗略带过,因为篇幅问题,并没有深究它的原理,后面的文章会进行补充。这一篇文章只是大概带大家过一下线程池的基本概览,深入讲解的地方不是很多,后续会通过源码深入研究其中比较重要的一些知识点。
726762
727763最后,就是这两周要考试了,会抽点时间出来简单应付一下学校考试了。然后,就是写这篇多线程的文章废了好多好多时间。一直不知从何写起。
728764
729- ## 参考
765+ ## 九 参考
730766
731767- 《Java 并发编程的艺术》
732768- [ Java Scheduler ScheduledExecutorService ScheduledThreadPoolExecutor Example] ( https://www.journaldev.com/2340/java-scheduler-scheduledexecutorservice-scheduledthreadpoolexecutor-example " Java Scheduler ScheduledExecutorService ScheduledThreadPoolExecutor Example ")
733769- [ java.util.concurrent.ScheduledThreadPoolExecutor Example] ( https://examples.javacodegeeks.com/core-java/util/concurrent/scheduledthreadpoolexecutor/java-util-concurrent-scheduledthreadpoolexecutor-example/ " java.util.concurrent.ScheduledThreadPoolExecutor Example ")
734770- [ ThreadPoolExecutor – Java Thread Pool Example] ( https://www.journaldev.com/1069/threadpoolexecutor-java-thread-pool-example-executorservice " ThreadPoolExecutor – Java Thread Pool Example ")
735771
736- ## 其他推荐阅读
772+ ## 十 其他推荐阅读
737773
738- - [ Java并发(三)线程池原理] ( https://www.cnblogs.com/warehouse/p/10720781.html )
774+ - [ Java并发(三)线程池原理] ( https://www.cnblogs.com/warehouse/p/10720781.html )
775+ - [ 如何优雅的使用和理解线程池] ( https://github.com/crossoverJie/JCSprout/blob/master/MD/ThreadPoolExecutor.md )
0 commit comments