图解定时任务线程池
线程池概念
我们上篇文章分析了ThreadPoolExecutor,如果要用一句话说明它的主要优势,就是线程置换。还有Executors工具类,极大的简化了研发人员工作。
我用一个图重复描述下线程池概念。多生产-多消费模型。
- 生产者将线程任务丢进线程池中,生产者就就结束了。
- 线程池控制消费者消费元素,消费者可以是1个或者多个,取决于线程池参数corePoolSize和maxPoolSize设置。
- 阻塞队列是用来装生产者丢进去的线程任务,如ArrayBlockingQueue,LinkedBlockingQueue,DelayedQueue等。如果生产者生产能力超过消费者消费能力,如果阻塞队列有长度限制并且超过队列长度线程池会执行饱和策略,如果队列没有长度限制,可也能出现OOM哦,因为线程任务可能把内存都撑爆了,这也是面试常考点哦!
详细概念可以翻看我上一篇文章《线程池面试必考问题》。
定时任务延时原理
还记得我们上面说的阻塞队列吗?定时任务线程池底层使用DelayedQueue实现的,这种延迟队列有一个最大的特点:按时出队列,大家都考过驾照吧,科目三考试的时候都是车上坐的是4个人,假设一个人考试需要花15分钟,那么考试学员队列看起来是这样的。
DelayedQueue底层需要实现Delayed接口同时需要实现getDelay方法和compareTo方法,getDelay方法用于计算出队列时间,一旦小于0就会出队列;compareTo方法用于按触发时间从小到大排序。这就是Schedule线程池任务延时原理,如果需要看案例代码,请参考我文章《并发队列:PriorityBlockingQueue和DelayQueue案例使用》。
scheduleWithFixedDelay和scheduleAtFixedRate区别
由上图可知:假设线程任务:耗时1秒,定时3秒执行,scheduleWithFixedDelay其实是4秒执行一次。
- scheduleWithFixedDelay:是以任务结束时间周期运行。
- scheduleAtFixedRate:是以固定周期运行。
FutureTask获取返回值
在ScheduledThreadPoolExecutor中,ScheduledFutureTask是获取定时任务返回值,继承FutureTask。我们看下FutureTask调用get阻塞简化流程图。
- 向线程池添加任务,任务被封装成ScheduledFutureTask并且实现Callable接口是为了获取任务返回值。
- 当客户端线程通过get方式获取线程池线程执行的返回值,客户端线程会阻塞直到线程池线程任务执行完。
在实际运用,我们一般拿返回值测试多线程性能。
Timer比较
- Timer是单线程,而且不带返回值。ScheduledThreadPoolExecutor是多线程的,采用线程复用代替创建新的线程,并且FutureTask带返回值。
- Timer线程调用sche方法,如果TimerTask出异常,Timer单线程直接挂掉退出,而ScheduledThreadPoolExecutor会捕获了异常,不影响其他消费者线程。下面是代码测试。
import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; /** * @author :jiaolian * @date :Created in 2021-02-25 13:50 * @description:Timer任务异常,Timer线程退出! * @modified By: * 公众号:叫练 */ public class TimerTaskExceptionTest { public static void main(String[] args) throws InterruptedException { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("first task"); } },0,1000); TimeUnit.SECONDS.sleep(3); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("second task"); int x = 5/0; } },0,1000); } }
如上代码:timer提交了first_task和second_task两个任务,3秒后,second_task执行5/0会抛出异常,此时timer线程会退出。如果换成ScheduledThreadPoolExecutor则不会影响first_task。在实际应用中,推荐用定时任务线程池中的方法去处理任务。
总结
今天我们介绍了线程池中面试中几个重要的面试点,整理出来希望能对你有帮助,写的比不全,同时还有许多需要修正的地方,希望亲们加以指正和点评,喜欢的请点赞加关注哦。点关注,不迷路,我是叫练【公众号】,微信号【jiaolian123abc】边叫边练。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
常见的初级排序算法,这次全搞懂
本文已被Github仓库收录 https://github.com/silently9527/JavaCore 程序员常用的IDEA插件:https://github.com/silently9527/ToolsetIdeaPlugin 完全开源的淘客项目:https://github.com/silently9527/mall-coupons-server 微信公众号:贝塔学Java 前言 相信所有的程序员刚开始接触到的算法都会是排序算法,因为排序在对数据处理和计算有这重要的地位,排序算法往往是其他算法的基础;本文我们就先从初级排序算法开始学习算法。 排序算法的模板 在开始之前我们先定义一个排序算法通用的模板,在后面的排序算法都会实现这个模板 public interface SortTemplate { void sort(Comparable[] array); default void print(Comparable[] array) { for (Comparable a : array) { System.out.print(a + " "); } } default b...
-
下一篇
Tor Browser 10.0.12 发布,隐私浏览器
Tor Browser 是一个基于 Firefox ESR (Firefox with extended support) 的 Web 浏览器,默认配置通过 Tor 和 Vidalia 实现了个人隐私保护和匿名。 此版本将桌面端 Firefox 更新为 78.8.0esr,将 Android Firefox 更新为 86.1.0。此外,Tor Browser 10.0.12 将 NoScript 更新为 11.2.2,将 Openssl 更新为 1.1.1j,并将 Tor 更新为 0.4.5.6。 自 Tor Browser 10.0.11 起的完整更改日志为: 所有平台 将 NoScript 更新到 11.2.2 将 Openssl 更新到 1.1.1j 将 Tor 更新至 0.4.5.6 Windows + OS X + Linux 将 Firefox 更新到 78.8.0esr Bug 40026:在桌面上的 about:tor 上创建调查横幅 Bug 40287:将 DDG 搜索从 POST 切换到 GET Android 将 Firefox 更新到 86.1.0 Bug 40...
相关文章
文章评论
共有0条评论来说两句吧...