并发编程从零开始(十四)-Executors工具类

发布时间:2022-07-01 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了并发编程从零开始(十四)-Executors工具类脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

并发编程从零开始(十四)-Executors工具类

12 Executors工具类

concurrent包提供了Executors工具类,利用它可以创建各种不同类型的线程池

12.1 四种对比

单线程的线程池:

并发编程从零开始(十四)-Executors工具类

固定数目线程的线程池:

并发编程从零开始(十四)-Executors工具类

每接收一个请求,就创建一个线程来执行:

并发编程从零开始(十四)-Executors工具类

单线程具有周期调度功能的线程池:

并发编程从零开始(十四)-Executors工具类

多线程,有调度功能的线程池:

并发编程从零开始(十四)-Executors工具类


12.2 最佳实践

不同类型的线程池,其实都是由前面的几个关键配置参数配置而成的。

在《阿里巴巴Java开发手册》中,明确禁止使用Executors创建线程池,并要求开发者直接使用ThreadPoolExector或ScheduledThreadPoolExecutor进行创建。这样做是为了强制开发者明确线程池的运行策略,使其对线程池的每个配置参数皆做到心中有数,以规避因使用不当而造成资耗尽的风险


13 ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor实现了按时间调度来执行任务

1. 延迟执行任务

并发编程从零开始(十四)-Executors工具类

并发编程从零开始(十四)-Executors工具类

2. 周期执行任务

并发编程从零开始(十四)-Executors工具类

并发编程从零开始(十四)-Executors工具类

区别如下:

AtFixedRate:按固定频率执行,与任务本身执行时间无关。但有个前提条件,任务执行时间必须小于间隔时间,例如间隔时间是5s,每5s执行一次任务,任务的执行时间必须小于5s。

WIThFixedDelay:按固定间隔执行,与任务本身执行时间有关。例如,任务本身执行时间是10s,间隔2s,则下一次开始执行的时间就是12s。


13.1 延迟执行和周期性执行的原理

ScheduledThreadPoolExecutor继承了ThreadPoolExecutor,这意味着其内部的数据结构和ThreadPoolExecutor是基本一样的,那它是如何实现延迟执行任务和周期性执行任务的呢?

延迟执行任务依靠的是DelayQueue。DelayQueue是 BlockingQueue的一种,其实现原理是二叉堆。

而周期性执行任务是执行完一个任务之后,再把该任务扔回到任务队列中,如此就可以对一个任务反复执行。

不过这里并没有使用DelayQueue,而是在ScheduledThreadPoolExecutor内部又实现了一个特定的DelayQueue

并发编程从零开始(十四)-Executors工具类

其原理和DelayQueue一样,但针对任务的取消进行了优化。下面主要讲延迟执行和周期性执行的实现过程。


13.2 延迟执行

并发编程从零开始(十四)-Executors工具类

传进去的是一个Runnable,外加延迟时间delay。在内部通过decorateTask(...)方法把Runnable包装成一个ScheduleFutureTask对象,而DelayedWorkQueue中存放的正是这种类型的对象,这种类型的对象一定实现了Delayed接口。

并发编程从零开始(十四)-Executors工具类

并发编程从零开始(十四)-Executors工具类

从上面的代码中可以看出,schedule()方法本身很简单,就是把提交的Runnable任务加上delay时间,转换成ScheduleDFutureTask对象,放入DelayedWorkerQueue中。任务的执行过程还是复用的ThreadPoolExecutor,延迟的控制是在DelayedWorkerQueue内部完成的。


13.4 执行周期

并发编程从零开始(十四)-Executors工具类

并发编程从零开始(十四)-Executors工具类

和schedule(...)方法的框架基本一样,也是包装一个ScheduledFutureTask对象,只是在延迟时间参数之外多了一个周期参数,然后放入DelayedWorkerQueue就结束了。

两个方法的区别在于一个传入的周期是一个负数,另一个传入的周期是一个正数,为什么要这样做呢?

用于生成任务序列号的sequencer,创建ScheduledFutureTask的时候使用:

并发编程从零开始(十四)-Executors工具类

并发编程从零开始(十四)-Executors工具类

并发编程从零开始(十四)-Executors工具类

withFixedDelay和atFixedRate的区别就体现在setNextRunTime里面。

如果是atFixedRate,PEriod>0,下一次开始执行时间等于上一次开始执行时间+period;

如果是withFixedDelay,period < 0,下一次开始执行时间等于triggerTime(-p),为now+(-period),now即上一次执行的结束时间。

脚本宝典总结

以上是脚本宝典为你收集整理的并发编程从零开始(十四)-Executors工具类全部内容,希望文章能够帮你解决并发编程从零开始(十四)-Executors工具类所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。