@@ -255,7 +255,7 @@ public class ThreadPoolExecutorDemo {
2552555 . ` workQueue ` :任务队列为 ` ArrayBlockingQueue ` ,并且容量为 100;
2562566 . ` handler ` :饱和策略为 ` CallerRunsPolicy ` 。
257257
258- 输出示例:
258+ ** Output: **
259259
260260```
261261pool-1-thread-2 Start. Time = Tue Nov 12 20:59:44 CST 2019
@@ -491,6 +491,23 @@ public class CallableDemo {
491491}
492492```
493493
494+ Output:
495+
496+ ```
497+ Wed Nov 13 13:40:41 CST 2019::pool-1-thread-1
498+ Wed Nov 13 13:40:42 CST 2019::pool-1-thread-2
499+ Wed Nov 13 13:40:42 CST 2019::pool-1-thread-3
500+ Wed Nov 13 13:40:42 CST 2019::pool-1-thread-4
501+ Wed Nov 13 13:40:42 CST 2019::pool-1-thread-5
502+ Wed Nov 13 13:40:42 CST 2019::pool-1-thread-3
503+ Wed Nov 13 13:40:43 CST 2019::pool-1-thread-2
504+ Wed Nov 13 13:40:43 CST 2019::pool-1-thread-1
505+ Wed Nov 13 13:40:43 CST 2019::pool-1-thread-4
506+ Wed Nov 13 13:40:43 CST 2019::pool-1-thread-5
507+ ```
508+
509+
510+
494511##五 几种常见的线程池详解
495512
496513### 5.1 FixedThreadPool
@@ -634,6 +651,8 @@ public class CallableDemo {
634651
635652## 六 ScheduledThreadPoolExecutor 详解
636653
654+ 这个在实际项目中基本不会被用到,所以对这部分大家只需要简单了解一下它的思想。
655+
637656### 6.1 简介
638657
639658** ` ScheduledThreadPoolExecutor ` 主要用来在给定的延迟后运行任务,或者定期执行任务。**
@@ -657,11 +676,11 @@ public class CallableDemo {
657676** ` ScheduledThreadPoolExecutor ` 的执行主要分为两大部分:**
658677
6596781 . 当调用 ` ScheduledThreadPoolExecutor ` 的 ** ` scheduleAtFixedRate() ` ** 方法或者** ` scheduleWirhFixedDelay() ` ** 方法时,会向 ` ScheduledThreadPoolExecutor ` 的 ** ` DelayQueue ` ** 添加一个实现了 ** ` RunnableScheduledFuture ` ** 接口的 ** ` ScheduledFutureTask ` ** 。
660- 2 . 线程池中的线程从 DelayQueue 中获取 ScheduledFutureTask,然后执行任务。
679+ 2 . 线程池中的线程从 ` DelayQueue ` 中获取 ` ScheduledFutureTask ` ,然后执行任务。
661680
662- ** ScheduledThreadPoolExecutor 为了实现周期性的执行任务,对 ThreadPoolExecutor 做了如下修改:**
681+ ** ` ScheduledThreadPoolExecutor ` 为了实现周期性的执行任务,对 ` ThreadPoolExecutor ` 做了如下修改:**
663682
664- - 使用 ** DelayQueue** 作为任务队列;
683+ - 使用 ** ` DelayQueue ` ** 作为任务队列;
665684- 获取任务的方不同
666685- 执行周期任务后,增加了额外的处理
667686
@@ -674,197 +693,14 @@ public class CallableDemo {
6746933 . 线程 1 修改 ScheduledFutureTask 的 time 变量为下次将要被执行的时间;
6756944 . 线程 1 把这个修改 time 之后的 ScheduledFutureTask 放回 DelayQueue 中(DelayQueue.add())。
676695
677- ### 6.4 ScheduledThreadPoolExecutor 使用示例
678-
679- 1 . 创建一个简单的实现 Runnable 接口的类(我们上面的例子已经实现过)
680-
681- 2 . 测试程序使用 ScheduledExecutorService 和 ScheduledThreadPoolExecutor 实现的 java 调度。
682-
683- ``` java
684- /**
685- * 使用ScheduledExecutorService和ScheduledThreadPoolExecutor实现的java调度程序示例程序。
686- */
687- public class ScheduledThreadPoolDemo {
688-
689- public static void main (String [] args ) throws InterruptedException {
690-
691- // 创建一个ScheduledThreadPoolExecutor对象
692- ScheduledExecutorService scheduledThreadPool = Executors . newScheduledThreadPool(5 );
693- // 计划在某段时间后运行
694- System . out. println(" Current Time = " + new Date ());
695- for (int i= 0 ; i< 3 ; i++ ){
696- Thread . sleep(1000 );
697- WorkerThread worker = new WorkerThread (" do heavy processing" );
698- // 创建并执行在给定延迟后启用的单次操作。
699- scheduledThreadPool. schedule(worker, 10 , TimeUnit . SECONDS );
700- }
701-
702- // 添加一些延迟让调度程序产生一些线程
703- Thread . sleep(30000 );
704- System . out. println(" Current Time = " + new Date ());
705- // 关闭线程池
706- scheduledThreadPool. shutdown();
707- while (! scheduledThreadPool. isTerminated()){
708- // 等待所有任务完成
709- }
710- System . out. println(" Finished all threads" );
711- }
712-
713- }
714- ```
715-
716- 运行结果:
717-
718- ```
719- Current Time = Wed May 30 17:11:16 CST 2018
720- pool-1-thread-1 Start. Time = Wed May 30 17:11:27 CST 2018
721- pool-1-thread-2 Start. Time = Wed May 30 17:11:28 CST 2018
722- pool-1-thread-3 Start. Time = Wed May 30 17:11:29 CST 2018
723- pool-1-thread-1 End. Time = Wed May 30 17:11:32 CST 2018
724- pool-1-thread-2 End. Time = Wed May 30 17:11:33 CST 2018
725- pool-1-thread-3 End. Time = Wed May 30 17:11:34 CST 2018
726- Current Time = Wed May 30 17:11:49 CST 2018
727- Finished all threads
728- ```
729-
730- #### 6.4.1 ScheduledExecutorService scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)方法
731-
732- 我们可以使用 ScheduledExecutorService scheduleAtFixedRate 方法来安排任务在初始延迟后运行,然后在给定的时间段内运行。
733-
734- 时间段是从池中第一个线程的开始,因此如果您将 period 指定为 1 秒并且线程运行 5 秒,那么只要第一个工作线程完成执行,下一个线程就会开始执行。
735-
736- ``` java
737- for (int i = 0 ; i < 3 ; i++ ) {
738- Thread . sleep(1000 );
739- WorkerThread worker = new WorkerThread (" do heavy processing" );
740- // schedule task to execute at fixed rate
741- scheduledThreadPool. scheduleAtFixedRate(worker, 0 , 10 ,
742- TimeUnit . SECONDS );
743- }
744- ```
745-
746- 输出示例:
747-
748- ```
749- Current Time = Wed May 30 17:47:09 CST 2018
750- pool-1-thread-1 Start. Time = Wed May 30 17:47:10 CST 2018
751- pool-1-thread-2 Start. Time = Wed May 30 17:47:11 CST 2018
752- pool-1-thread-3 Start. Time = Wed May 30 17:47:12 CST 2018
753- pool-1-thread-1 End. Time = Wed May 30 17:47:15 CST 2018
754- pool-1-thread-2 End. Time = Wed May 30 17:47:16 CST 2018
755- pool-1-thread-3 End. Time = Wed May 30 17:47:17 CST 2018
756- pool-1-thread-1 Start. Time = Wed May 30 17:47:20 CST 2018
757- pool-1-thread-4 Start. Time = Wed May 30 17:47:21 CST 2018
758- pool-1-thread-2 Start. Time = Wed May 30 17:47:22 CST 2018
759- pool-1-thread-1 End. Time = Wed May 30 17:47:25 CST 2018
760- pool-1-thread-4 End. Time = Wed May 30 17:47:26 CST 2018
761- pool-1-thread-2 End. Time = Wed May 30 17:47:27 CST 2018
762- pool-1-thread-1 Start. Time = Wed May 30 17:47:30 CST 2018
763- pool-1-thread-3 Start. Time = Wed May 30 17:47:31 CST 2018
764- pool-1-thread-5 Start. Time = Wed May 30 17:47:32 CST 2018
765- pool-1-thread-1 End. Time = Wed May 30 17:47:35 CST 2018
766- pool-1-thread-3 End. Time = Wed May 30 17:47:36 CST 2018
767- pool-1-thread-5 End. Time = Wed May 30 17:47:37 CST 2018
768- pool-1-thread-1 Start. Time = Wed May 30 17:47:40 CST 2018
769- pool-1-thread-2 Start. Time = Wed May 30 17:47:41 CST 2018
770- Current Time = Wed May 30 17:47:42 CST 2018
771- pool-1-thread-1 End. Time = Wed May 30 17:47:45 CST 2018
772- pool-1-thread-2 End. Time = Wed May 30 17:47:46 CST 2018
773- Finished all threads
774-
775- Process finished with exit code 0
776-
777- ```
778-
779- #### 6.4.2 ScheduledExecutorService scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)方法
780-
781- ScheduledExecutorService scheduleWithFixedDelay 方法可用于以初始延迟启动周期性执行,然后以给定延迟执行。 延迟时间是线程完成执行的时间。
782-
783- ``` java
784- for (int i = 0 ; i < 3 ; i++ ) {
785- Thread . sleep(1000 );
786- WorkerThread worker = new WorkerThread (" do heavy processing" );
787- scheduledThreadPool. scheduleWithFixedDelay(worker, 0 , 1 ,
788- TimeUnit . SECONDS );
789- }
790- ```
791-
792- 输出示例:
793-
794- ```
795- Current Time = Wed May 30 17:58:09 CST 2018
796- pool-1-thread-1 Start. Time = Wed May 30 17:58:10 CST 2018
797- pool-1-thread-2 Start. Time = Wed May 30 17:58:11 CST 2018
798- pool-1-thread-3 Start. Time = Wed May 30 17:58:12 CST 2018
799- pool-1-thread-1 End. Time = Wed May 30 17:58:15 CST 2018
800- pool-1-thread-2 End. Time = Wed May 30 17:58:16 CST 2018
801- pool-1-thread-1 Start. Time = Wed May 30 17:58:16 CST 2018
802- pool-1-thread-3 End. Time = Wed May 30 17:58:17 CST 2018
803- pool-1-thread-4 Start. Time = Wed May 30 17:58:17 CST 2018
804- pool-1-thread-2 Start. Time = Wed May 30 17:58:18 CST 2018
805- pool-1-thread-1 End. Time = Wed May 30 17:58:21 CST 2018
806- pool-1-thread-1 Start. Time = Wed May 30 17:58:22 CST 2018
807- pool-1-thread-4 End. Time = Wed May 30 17:58:22 CST 2018
808- pool-1-thread-2 End. Time = Wed May 30 17:58:23 CST 2018
809- pool-1-thread-2 Start. Time = Wed May 30 17:58:23 CST 2018
810- pool-1-thread-4 Start. Time = Wed May 30 17:58:24 CST 2018
811- pool-1-thread-1 End. Time = Wed May 30 17:58:27 CST 2018
812- pool-1-thread-2 End. Time = Wed May 30 17:58:28 CST 2018
813- pool-1-thread-1 Start. Time = Wed May 30 17:58:28 CST 2018
814- pool-1-thread-2 Start. Time = Wed May 30 17:58:29 CST 2018
815- pool-1-thread-4 End. Time = Wed May 30 17:58:29 CST 2018
816- pool-1-thread-4 Start. Time = Wed May 30 17:58:30 CST 2018
817- pool-1-thread-1 End. Time = Wed May 30 17:58:33 CST 2018
818- pool-1-thread-2 End. Time = Wed May 30 17:58:34 CST 2018
819- pool-1-thread-1 Start. Time = Wed May 30 17:58:34 CST 2018
820- pool-1-thread-2 Start. Time = Wed May 30 17:58:35 CST 2018
821- pool-1-thread-4 End. Time = Wed May 30 17:58:35 CST 2018
822- pool-1-thread-4 Start. Time = Wed May 30 17:58:36 CST 2018
823- pool-1-thread-1 End. Time = Wed May 30 17:58:39 CST 2018
824- pool-1-thread-2 End. Time = Wed May 30 17:58:40 CST 2018
825- pool-1-thread-5 Start. Time = Wed May 30 17:58:40 CST 2018
826- pool-1-thread-4 End. Time = Wed May 30 17:58:41 CST 2018
827- pool-1-thread-2 Start. Time = Wed May 30 17:58:41 CST 2018
828- Current Time = Wed May 30 17:58:42 CST 2018
829- pool-1-thread-5 End. Time = Wed May 30 17:58:45 CST 2018
830- pool-1-thread-2 End. Time = Wed May 30 17:58:46 CST 2018
831- Finished all threads
832- ```
833-
834- #### 6.4.3 scheduleWithFixedDelay() vs scheduleAtFixedRate()
835-
836- scheduleAtFixedRate(...)将延迟视为两个任务开始之间的差异(即定期调用)
837- scheduleWithFixedDelay(...)将延迟视为一个任务结束与下一个任务开始之间的差异
838-
839- > ** scheduleAtFixedRate():** 创建并执行在给定的初始延迟之后,随后以给定的时间段首先启用的周期性动作; 那就是执行将在 initialDelay 之后开始,然后 initialDelay+period ,然后是 initialDelay + 2 \* period ,等等。 如果任务的执行遇到异常,则后续的执行被抑制。 否则,任务将仅通过取消或终止执行人终止。 如果任务执行时间比其周期长,则后续执行可能会迟到,但不会同时执行。
840- > ** scheduleWithFixedDelay() :** 创建并执行在给定的初始延迟之后首先启用的定期动作,随后在一个执行的终止和下一个执行的开始之间给定的延迟。 如果任务的执行遇到异常,则后续的执行被抑制。 否则,任务将仅通过取消或终止执行终止。
841-
842- ## 七 各种线程池的适用场景介绍
843-
844- - ** FixedThreadPool:** 适用于为了满足资源管理需求,而需要限制当前线程数量的应用场景。它适用于负载比较重的服务器;
845-
846- - ** SingleThreadExecutor:** 适用于需要保证顺序地执行各个任务并且在任意时间点,不会有多个线程是活动的应用场景。
847-
848- ** CachedThreadPool:** 适用于执行很多的短期异步任务的小程序,或者是负载较轻的服务器;
849-
850- ** ScheduledThreadPoolExecutor:** 适用于需要多个后台执行周期任务,同时为了满足资源管理需求而需要限制后台线程的数量的应用场景,
851-
852- ** SingleThreadScheduledExecutor:** 适用于需要单个后台线程执行周期任务,同时保证顺序地执行各个任务的应用场景。
853-
854- ## 八 总结
855-
856- 本节只是简单的介绍了一下使用线程池的好处,然后花了大量篇幅介绍 Executor 框架。详细介绍了 Executor 框架中 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor,并且通过实例详细讲解了 ScheduledThreadPoolExecutor 的使用。对于 FutureTask 只是粗略带过,因为篇幅问题,并没有深究它的原理,后面的文章会进行补充。这一篇文章只是大概带大家过一下线程池的基本概览,深入讲解的地方不是很多,后续会通过源码深入研究其中比较重要的一些知识点。
857-
858- 最后,就是这两周要考试了,会抽点时间出来简单应付一下学校考试了。然后,就是写这篇多线程的文章废了好多好多时间。一直不知从何写起。
859-
860- ## 九 参考
696+ ## 七 参考
861697
862698- 《Java 并发编程的艺术》
863699- [ Java Scheduler ScheduledExecutorService ScheduledThreadPoolExecutor Example] ( https://www.journaldev.com/2340/java-scheduler-scheduledexecutorservice-scheduledthreadpoolexecutor-example " Java Scheduler ScheduledExecutorService ScheduledThreadPoolExecutor Example ")
864700- [ java.util.concurrent.ScheduledThreadPoolExecutor Example] ( https://examples.javacodegeeks.com/core-java/util/concurrent/scheduledthreadpoolexecutor/java-util-concurrent-scheduledthreadpoolexecutor-example/ " java.util.concurrent.ScheduledThreadPoolExecutor Example ")
865701- [ ThreadPoolExecutor – Java Thread Pool Example] ( https://www.journaldev.com/1069/threadpoolexecutor-java-thread-pool-example-executorservice " ThreadPoolExecutor – Java Thread Pool Example ")
866702
867- ## 十 其他推荐阅读
703+ ## 八 其他推荐阅读
868704
869705- [ Java 并发(三)线程池原理] ( https://www.cnblogs.com/warehouse/p/10720781.html " Java并发(三)线程池原理 ")
870706- [ 如何优雅的使用和理解线程池] ( https://github.com/crossoverJie/JCSprout/blob/master/MD/ThreadPoolExecutor.md " 如何优雅的使用和理解线程池 ")
0 commit comments