摘要:JDK 1.5开始提供Scheduled Thread PoolExecutor类,Scheduled Thread Pool Executor类继承Thread Pool Executor类重用线程池实现了任务的周期性调度功能。

本文分享自华为云社区《【高并发】ScheduledThreadPoolExecutor与Timer的区别和简单示例》,作者:冰 河 。

JDK 1.5开始提供ScheduledThreadPoolExecutor类,ScheduledThreadPoolExecutor类继承ThreadPoolExecutor类重用线程池实现了任务的周期性调度功能。在JDK 1.5之前,实现任务的周期性调度主要使用的是Timer类和TimerTask类。本文,就简单介绍下ScheduledThreadPoolExecutor类与Timer类的区别,ScheduledThreadPoolExecutor类相比于Timer类来说,究竟有哪些优势,以及二者分别实现任务调度的简单示例。

二者的区别

线程角度

  • Timer是单线程模式,如果某个TimerTask任务的执行时间比较久,会影响到其他任务的调度执行。
  • ScheduledThreadPoolExecutor是多线程模式,并且重用线程池,某个ScheduledFutureTask任务执行的时间比较久,不会影响到其他任务的调度执行。

系统时间敏感度

  • Timer调度是基于操作系统的绝对时间的,对操作系统的时间敏感,一旦操作系统的时间改变,则Timer的调度不再精确。
  • ScheduledThreadPoolExecutor调度是基于相对时间的,不受操作系统时间改变的影响。

是否捕获异常

  • Timer不会捕获TimerTask抛出的异常,加上Timer又是单线程的。一旦某个调度任务出现异常,则整个线程就会终止,其他需要调度的任务也不再执行。
  • ScheduledThreadPoolExecutor基于线程池来实现调度功能,某个任务抛出异常后,其他任务仍能正常执行。

任务是否具备优先级

  • Timer中执行的TimerTask任务整体上没有优先级的概念,只是按照系统的绝对时间来执行任务。
  • ScheduledThreadPoolExecutor中执行的ScheduledFutureTask类实现了java.lang.Comparable接口和java.util.concurrent.Delayed接口,这也就说明了ScheduledFutureTask类中实现了两个非常重要的方法,一个是java.lang.Comparable接口的compareTo方法,一个是java.util.concurrent.Delayed接口的getDelay方法。在ScheduledFutureTask类中compareTo方法方法实现了任务的比较,距离下次执行的时间间隔短的任务会排在前面,也就是说,距离下次执行的时间间隔短的任务的优先级比较高。而getDelay方法则能够返回距离下次任务执行的时间间隔。

是否支持对任务排序

  • Timer不支持对任务的排序。
  • ScheduledThreadPoolExecutor类中定义了一个静态内部类DelayedWorkQueue,DelayedWorkQueue类本质上是一个有序队列,为需要调度的每个任务按照距离下次执行时间间隔的大小来排序

能否获取返回的结果

  • Timer中执行的TimerTask类只是实现了java.lang.Runnable接口,无法从TimerTask中获取返回的结果。
  • ScheduledThreadPoolExecutor中执行的ScheduledFutureTask类继承了FutureTask类,能够通过Future来获取返回的结果。

通过以上对ScheduledThreadPoolExecutor类和Timer类的分析对比,相信在JDK 1.5之后,就没有使用Timer来实现定时任务调度的必要了。

二者简单的示例

这里,给出使用Timer和ScheduledThreadPoolExecutor实现定时调度的简单示例,为了简便,我这里就直接使用匿名内部类的形式来提交任务。

Timer类简单示例

源代码示例如下所示。

package io.binghe.concurrent.lab09;
import java.util.Timer;
import java.util.TimerTask;
/**
* @author binghe
* @version 1.0.0
* @description 测试Timer
*/
public class TimerTest {
public static void main(String[] args) throws InterruptedException {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("测试Timer类");
}
}, 1000, 1000);
Thread.sleep(10000);
timer.cancel();
}
}

运行结果如下所示。

测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类

ScheduledThreadPoolExecutor类简单示例

源代码示例如下所示。

package io.binghe.concurrent.lab09;
import java.util.concurrent.*;
/**
* @author binghe
* @version 1.0.0
* @description 测试ScheduledThreadPoolExecutor
*/
public class ScheduledThreadPoolExecutorTest {
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("测试测试ScheduledThreadPoolExecutor");
}
}, 1, 1, TimeUnit.SECONDS);
//主线程休眠10秒
Thread.sleep(10000);
System.out.println("正在关闭线程池...");
// 关闭线程池
scheduledExecutorService.shutdown();
boolean isClosed;
// 等待线程池终止
do {
isClosed = scheduledExecutorService.awaitTermination(1, TimeUnit.DAYS);
System.out.println("正在等待线程池中的任务执行完成");
} while(!isClosed);
System.out.println("所有线程执行结束,线程池关闭");
}
}

运行结果如下所示。

测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
正在关闭线程池...
测试测试ScheduledThreadPoolExecutor
正在等待线程池中的任务执行完成
所有线程执行结束,线程池关闭

注意:关于Timer和ScheduledThreadPoolExecutor还有其他的使用方法,这里,我就简单列出以上两个使用示例,更多的使用方法大家可以自行实现。

点击关注,第一时间了解华为云新鲜技术~

实例分析Scheduled Thread Pool Executor与Timer的区别的更多相关文章

  1. 通过Thread Pool Executor类解析线程池执行任务的核心流程

    摘要:ThreadPoolExecutor是Java线程池中最核心的类之一,它能够保证线程池按照正常的业务逻辑执行任务,并通过原子方式更新线程池每个阶段的状态. 本文分享自华为云社区<[高并发] ...

  2. [图解tensorflow源码] 线程池模块分析 (CPU thread pool device)

  3. 从一个简单的小实例分析JSP+Servelt与JSP+Struts2框架的区别

    最近在学struts2,struts2相比以前的JSP+Servlet,在处理流程上的更简单,我们就一个小实例来具体分析一下. 实例内容如下: 实现一个简单的注册页面包括:用户名.密码.重复密码.年龄 ...

  4. ThreadPoolExecutor – Java Thread Pool Example(如何使用Executor框架创建一个线程池)

    Java thread pool manages the pool of worker threads, it contains a queue that keeps tasks waiting to ...

  5. ThreadPoolExecutor – Java Thread Pool Example

    https://www.journaldev.com/1069/threadpoolexecutor-java-thread-pool-example-executorservice   Java t ...

  6. ThreadPoolExecutor – Java Thread Pool Example(java线程池创建和使用)

    Java thread pool manages the pool of worker threads, it contains a queue that keeps tasks waiting to ...

  7. [源码分析] 并行分布式任务队列 Celery 之 Timer & Heartbeat

    [源码分析] 并行分布式任务队列 Celery 之 Timer & Heartbeat 目录 [源码分析] 并行分布式任务队列 Celery 之 Timer & Heartbeat 0 ...

  8. DUBBO Thread pool is EXHAUSTED!

    一.问题 在测试环境遇到的异常信息,如下: 16-10-17 00:00:00.033 [New I/O server worker #1-6] WARN  com.alibaba.dubbo.com ...

  9. MySQL学习分享--Thread pool实现

    基于<MySQL学习分享--Thread pool>对Thread pool架构设计的详细了解,本文主要对Thread pool的实现进行分析,并根据Mariadb和Percona提供的开 ...

随机推荐

  1. AlexNet—论文分析及复现

    AlexNet卷积神经网络是由Alex Krizhevsky等人在2012年的ImagNet图像识别大赛获得冠军的一个卷积神经网络,该网络放到现在相对简单,但也是深度学习不错的卷积神经网络.论文:&l ...

  2. SpringBoot 集成 FreeMarker 导出 Word 模板文件(底部附源码)

    思路解说 word 模板文件(doc 或 docx 文件)另存为 xml 文件 将后缀 xml 改成 html:大部分文档会改成 ftl(FreeMarker 的后缀名),因为 word 文件另存为 ...

  3. 小白之Python基础(二)

    一.字符串 1.字符串编码发展: 1)ASCII码: 一个字节去表示 (8个比特(bit)作为一个字节(byte),因此,一个字节能表示的最大的整数就是255(二进制11111111 = 十进制255 ...

  4. 关于 CDH 环境中部署 Dolphinscheduler 出现 hive-jdbc 包冲突的解决办法

    目前社区小伙伴经常反映在 cdh 环境中部署 Dolphinscheduler 出现 hive 包冲突的问题,报错日志信息如下: [WARN] 2020-04-29 09:55:30.815 org. ...

  5. JavaDoc文档生成详细操作

    JavaDoc练习 JavaDoc是一种将注释生成HTML文档的技术,是用来生成自己API文档的. 参数信息 /* @author 作者名 @version 版本号 @since 知名最早需要使用的j ...

  6. java-servlet过滤器和监听

    1 过滤器 过滤器是什么?servlet规范当中定义的一种特殊的组件,用于拦截容器的调用.注:容器收到请求之后,如果有过滤器,会先调用过滤器,然后在调用servlet. 如何写一个过滤器? 写一个ja ...

  7. 使springAOP生效不一定要加@EnableAspectJAutoProxy注解

    在上篇文章<springAOP和AspectJ有关系吗?如何使用springAOP面向切面编程>中遗留了一个问题,那就是在springboot中使用springAOP需要加@EnableA ...

  8. laravel框架(完整上传到数据库,不提交图片)(以提交员工信息为例)

    第一步:使用PHP终端创建一个名为blog的框架 composer create-project --prefer-dist laravel/laravel blog 7.x 创建好之后,在框架中找到 ...

  9. 【三维地图】开发攻略 —— 详解“GeoJSON”技术和应用场景

    GeoJSON ,一个用于存储地理信息的数据格式.GoeJSON对象可以表示几何.特征或特征集合,支持:点.线.面.多点.多线.多面和几何集合.在基于平面地图,三维地图中都需要用到的一种数据类型. 由 ...

  10. 第十三章 k8s的GUI资源管理插件--dashboard

    1.部署Kubernetes-dashboard 1.1 准备dashboard镜像 在10.4.7.200上操作 [root@hdss7-200 ~]# docker pull k8scn/kube ...