定时且周期性的任务研究II--ScheduledThreadPoolExecutor
http://victorzhzh.iteye.com/blog/1011635
上一篇中我们看到了Timer的不足之处,本篇我们将围绕这些不足之处看看ScheduledThreadPoolExecutor是如何优化的。
为了研究方便我们需要两个类:
- public class Task1 implements Callable<String> {
- @Override
- public String call() throws Exception {
- String base = "abcdefghijklmnopqrstuvwxyz0123456789";
- Random random = new Random();
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < 10; i++) {
- int number = random.nextInt(base.length());
- sb.append(base.charAt(number));
- }
- System.out.println("Task1 running: " + new Date());
- return sb.toString();
- }
- }
生成含有10个字符的字符串,使用Callable接口目的是我们不再任务中直接输出结果,而主动取获取任务的结果
- public class LongTask implements Callable<String> {
- @Override
- public String call() throws Exception {
- System.out.println("LongTask running: "+new Date());
- TimeUnit.SECONDS.sleep(10);
- return "success";
- }
- }
长任务类,这里我们让任务沉睡10秒然后返回一个“success”
下面我们来分析一下ScheduledThreadPoolExecutor:
1、Timer中单线程问题是否在ScheduledThreadPoolExecutor中存在?
我们先来看一下面的程序:
- public class ScheduledThreadPoolExec {
- public static void main(String[] args) throws InterruptedException,
- ExecutionException {
- <strong><span style="color: #ff0000;">ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
- 2);</span>
- </strong>
- ScheduledFuture future1 = executor.schedule(new Task1(), 5,
- TimeUnit.SECONDS);
- ScheduledFuture future2 = executor.schedule(new LongTask(), 3,
- TimeUnit.SECONDS);
- BlockingQueue<ScheduledFuture> blockingQueue = new ArrayBlockingQueue<ScheduledFuture>(
- 2, true);
- blockingQueue.add(future2);
- blockingQueue.add(future1);
- System.out.println(new Date());
- while (!blockingQueue.isEmpty()) {
- ScheduledFuture future = blockingQueue.poll();
- if (!future.isDone())
- blockingQueue.add(future);
- else
- System.out.println(future.get());
- }
- System.out.println(new Date());
- executor.shutdown();
- }
- }
首先,我们定义了一个ScheduledThreadPoolExecutor它的池长度是2。接着提交了两个任务:第一个任务将延迟5秒执行,第二个任务将延迟3秒执行。我们建立了一个BlockingQueue,用它来存储了ScheduledFuture,使用ScheduledFuture可以获得任务的执行结果。在一个while循环中,我们每次将一个ScheduledFuture从队列中弹出,验证它是否被执行,如果没有被执行则再次将它加入队列中,如果被执行了,这使用ScheduledFuture的get方法获取任务执行的结果。看一下执行结果:
- Thu Apr 21 19:23:02 CST 2011
- LongTask running: Thu Apr 21 19:23:05 CST 2011
- Task1 running: Thu Apr 21 19:23:07 CST 2011
- h1o2wd942e
- success
- Thu Apr 21 19:23:15 CST 2011
我们看到长任务先运行,因为长任务只等待了3秒,然后是输出字符串的任务运行,两个任务开始时间相差2秒,而先输出了字符串而后才是长任务运行的结果success,最后我们查看一下整体的开始和结束时间相差了13秒。
这说明在ScheduledThreadPoolExecutor中它不是以一个线程运行任务的,而是以多个线程,如果用一个线程运行任务,那么长任务运行完之前是不会运行输出字符串任务的。其实这个“多个任务“是我们自己指定的注意一下标红的代码,如果我们把这行代码改为:
- ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
那么运行结果就会发生变化,
- Thu Apr 21 19:36:56 CST 2011
- LongTask running: Thu Apr 21 19:36:59 CST 2011
- success
- Task1 running: Thu Apr 21 19:37:09 CST 2011
- y981iqd0or
- Thu Apr 21 19:37:09 CST 2011
这时其实和使用Timer运行结果是一样的。任务是在一个线程里顺序执行的。
2、Timer中一但有运行时异常报出后续任务是否还会正常运行?
为了研究这个问题,我们还是需要一个能够抛出异常的任务,如下:
- public class TimerExceptionTask extends TimerTask {
- @Override
- public void run() {
- System.out.println("TimerExceptionTask: "+new Date());
- throw new RuntimeException();
- }
- }
我们对上面运行任务的代码做一点点小小的修改,先运行两个抛出异常的任务,如下:
- public class ScheduledThreadPoolExec {
- public static void main(String[] args) throws InterruptedException,
- ExecutionException {
- ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
- 2);
- ScheduledFuture future1 = executor.schedule(new Task1(), 5,
- TimeUnit.SECONDS);
- ScheduledFuture future2 = executor.schedule(new LongTask(), 3,
- TimeUnit.SECONDS);
- <strong><span style="color: #ff0000;">executor.schedule(new TimerExceptionTask(), 1, TimeUnit.SECONDS);
- executor.schedule(new TimerExceptionTask(), 2, TimeUnit.SECONDS);</span>
- </strong>
- BlockingQueue<ScheduledFuture> blockingQueue = new ArrayBlockingQueue<ScheduledFuture>(
- 2, true);
- blockingQueue.add(future2);
- blockingQueue.add(future1);
- System.out.println(new Date());
- while (!blockingQueue.isEmpty()) {
- ScheduledFuture future = blockingQueue.poll();
- if (!future.isDone())
- blockingQueue.add(future);
- else
- System.out.println(future.get());
- }
- System.out.println(new Date());
- executor.shutdown();
- }
- }
注意,标红的代码,如果这两个代码抛出错误后会影响后续任务,那么就应该在此终止,但是看一下结果,
- Thu Apr 21 19:40:15 CST 2011
- TimerExceptionTask: Thu Apr 21 19:40:16 CST 2011
- TimerExceptionTask: Thu Apr 21 19:40:17 CST 2011
- LongTask running: Thu Apr 21 19:40:18 CST 2011
- Task1 running: Thu Apr 21 19:40:20 CST 2011
- v5gcf01iiz
- success
- Thu Apr 21 19:40:28 CST 2011
后续任务仍然执行,可能会有朋友说:“你上面的池设置的是2,所以很有可能是那两个抛出异常的任务都在同一个线程中执行,而另一个线程执行了后续的任务”。那我们就把ScheduledThreadPoolExecutor设置成1看看,结果如下:
- Thu Apr 21 19:43:00 CST 2011
- TimerExceptionTask: Thu Apr 21 19:43:01 CST 2011
- TimerExceptionTask: Thu Apr 21 19:43:02 CST 2011
- LongTask running: Thu Apr 21 19:43:03 CST 2011
- success
- Task1 running: Thu Apr 21 19:43:13 CST 2011
- 33kgv8onnd
- Thu Apr 21 19:43:13 CST 2011
后续任务也执行了,所以说ScheduledThreadPoolExecutor不会像Timer那样有线程泄漏现象。
对于周期性执行和Timer很类似这里就不再举例了。
转载于:https://www.cnblogs.com/senior-engineer/p/5000143.html
定时且周期性的任务研究II--ScheduledThreadPoolExecutor相关推荐
- 如何调度spark程序_如何定时,周期性的运行程序?Python APScheduler实现任务灵活调度...
在我们的开发工作中,时常会有这样的开发需求,如需要定时或者周期性的运行某些程序,因此经常用到一些定时服务,如在 Linux系统中使用 Crond 服务实现程序的定时运行. 在 Python中也有这样的 ...
- floquet端口x极化入射波_AnsoftHFSS在周期性异向介质研究中的仿真方法.pdf
AnsoftHFSS在周期性异向介质研究中的仿真方法 Ansoft 2008 优秀论文 Ansoft HFSS 在周期性异向介质研究中的仿真方法 龚建强,褚庆昕 (华南理工大学电子与信息学院 广州 5 ...
- Java四种线程创建的思路
一.哪四种 传统的是继承thread类和实现runnable接口,java5以后又有实现callable接口和java的线程池获得. callable相比于runnable,多了返回值,抛出了异常. ...
- java线程不执行_java线程池,阿里为什么不允许使用Executors?
带着问题 阿里Java代码规范为什么不允许使用Executors快速创建线程池? 下面的代码输出是什么? ThreadPoolExecutor executor = new ThreadPoolExe ...
- PHP中空格占位数吗,html内的空格占位
NPOI读取Excel 数据 转... public DataTable am_Decode() { DataTable table = new DataTable(); string[] strAs ...
- td lte pss同步matlab仿真,TD-LTE系统小区搜索PSS定时同步的研究
随着移动互联网的发展,终端用户对于数据业务的需求呈爆炸式的增长,为了满足用户对移动无线宽带的需求,TD-LTE网络成为移动互联网的重要解决方案.在TD-LTE系统中,小区搜索是无线链路的关键步骤,是用 ...
- matlab对有周期性噪声的图像去噪,数字图像中去除周期性噪声研究.doc
摘要:图像增强是数字图像处理相对简单却最具艺术性的领域之一,其目的是消除噪声,显现被模糊的细节或突出感兴趣区域.经常采用的手段分空域和频域两类,其中频域更是给我们提供了不同的视角,简化了许多复杂的算法 ...
- 11.定时任务定时线程池详解
3.1 新增定时任务池 11.定时任务&定时线程池详解 当我们不用任务框架时,我们想自己写一个定时任务时,我们能想起那个工具类呢?Timer ?还有吗?不知道了,下面我们要讲下Schedu ...
- @Scheduled定时
目录 一.项目中常遇到的坑 二.线程池相关内容 2.1 .线程池的创建: 2.1.1 Java通过Executors提供四种线程池 三. @Scheduled的工作机制,源码分析 1.@Schedu ...
最新文章
- php扇形分布图,PHP制作3D扇形统计图以及对图片进行缩放操作实例
- 工业互联网不只是网络:网络是基础,平台是关键
- Mybatis系列(三):Mybatis实现关联表查询
- 有网友提问,关于本地XML转JSON的小工具
- 计算机硬件知识教学的信息化手段,《计算机硬件组成》教学设计
- c语言uint32_使C语言实现面向对象的三个要素,你掌握了吗?
- 现在的年轻人不够努力了吗?是什么原因?
- Python 在数据科学中一直打压 R 语言?
- TableView Within Alert
- [转]软件开发的“三重门”
- 修改docker网桥模式下的网络地址
- Master Reactor Manager Worker TaskWorker(Task)
- NOIp2010 机器翻译
- 马上:网络故障排查的思路和方法
- 【笔记整理】网络攻防技术
- 【字符编码转换】使用iconv
- Android静默拍照(无感知拍照)
- WSL2 安装 CUDA(Win11)
- 云服务器系统结构图,云服务器系统结构图
- 歇逼了兄弟,心态崩了
热门文章
- 安卓逆向—霸哥磁力搜索apk过签名校验
- Ubuntu 18.04.6 允许root用户登录桌面
- 智星云服务器之云主机使用教程简记
- Failed to load the JNI shared library 的解决方法
- 计算机网络技术评估与备选方案,计算机网络技术业个人职业生涯规划书.doc
- 深度学习与OpenCV DNN模块:权威指南
- 选用pg的优点和缺点
- 记录---Testin上新手测试用例设计实战---碎乐3.2.0
- 【以太坊】什么是雷电网络 Raiden network
- python是自由开放源代码软件_开放源代码定义之历史篇