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 | +## 七 参考 |
861 | 697 |
|
862 | 698 | - 《Java 并发编程的艺术》
|
863 | 699 | - [Java Scheduler ScheduledExecutorService ScheduledThreadPoolExecutor Example](https://www.journaldev.com/2340/java-scheduler-scheduledexecutorservice-scheduledthreadpoolexecutor-example "Java Scheduler ScheduledExecutorService ScheduledThreadPoolExecutor Example")
|
864 | 700 | - [java.util.concurrent.ScheduledThreadPoolExecutor Example](https://examples.javacodegeeks.com/core-java/util/concurrent/scheduledthreadpoolexecutor/java-util-concurrent-scheduledthreadpoolexecutor-example/ "java.util.concurrent.ScheduledThreadPoolExecutor Example")
|
865 | 701 | - [ThreadPoolExecutor – Java Thread Pool Example](https://www.journaldev.com/1069/threadpoolexecutor-java-thread-pool-example-executorservice "ThreadPoolExecutor – Java Thread Pool Example")
|
866 | 702 |
|
867 |
| -## 十 其他推荐阅读 |
| 703 | +## 八 其他推荐阅读 |
868 | 704 |
|
869 | 705 | - [Java 并发(三)线程池原理](https://www.cnblogs.com/warehouse/p/10720781.html "Java并发(三)线程池原理")
|
870 | 706 | - [如何优雅的使用和理解线程池](https://github.com/crossoverJie/JCSprout/blob/master/MD/ThreadPoolExecutor.md "如何优雅的使用和理解线程池")
|
0 commit comments