java高并发ScheduledThreadPoolExecutor与Timer区别
作者:冰河 发布时间:2023-08-11 03:08:29
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还有其他的使用方法,这里,我就简单列出以上两个使用示例,更多的使用方法大家可以自行实现。
来源:https://www.cnblogs.com/binghe001/p/16784569.html


猜你喜欢
- 本文为大家分享了java多线程的简单实现及线程池实例,供大家参考,具体内容如下一、多线程的两种实现方式1、继承Thread类的多线程/**
- 顺序语句顺序顾名思义就是程序自上而下执行public class User { public static voi
- 模糊查询Spring Data Jpa的使用可以减少开发者对sql语句的编写,甚至完全不需要编写sql语句。但是,开发过程中总会遇到各种复杂
- 目录前言Hello World1.可以在 Spring Initializr上面添加,也可以手动在 pom.xml中添加如下代码∶2. 编写
- 本文实例讲述了Java实现对两个List快速去重并排序操作。分享给大家供大家参考,具体如下:1:去重并排序package twolist;i
- 简介Exchanger是一个用于线程间数据交换的工具类,它提供一个公共点,在这个公共点,两个线程可以交换彼此的数据。当一个线程调用excha
- 本文实例讲述了Android开发使用Drawable绘制圆角与圆形图案功能。分享给大家供大家参考,具体如下:1. 创建类RoundCircl
- 本文实现初次设置密码验证过程,首先实现如下效果布局如下:<?xml version="1.0" encoding=
- C#用户定义类型转换•用于自定义类和结构能够进行隐式转换和显示转换.例如:将一个自定义类类型转换成整型,浮点型等,反之亦然.C#提供隐式转换
- 一、ArrayList简介在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:ArrayList底层是一段连
- 本文实例讲述了java实现单词搜索迷宫游戏。分享给大家供大家参考。具体分析如下:我们在杂志上,经常能够看到找单词的小游戏,在一个二维表格中,
- 在项目开发中,我们经常需要进行动态添加组件,其中可添加的部分有两项:布局和组件 其中,添加的布局主要有RelativeLayout
- 比如在窗体中显示时间:错误思路一:我在窗体结构函数中写入一个死循环,每隔一秒显示一次当前时间public Form6() &n
- 一、前言高效、合理的使用hibernate-validator校验框架可以提高程序的可读性,以及减少不必要的代码逻辑。接下来会介绍一下常用一
- 最近在开发浏览器碰到这么一个需求:点击地址栏的时候,需要全选并调出键盘,再次点击就取消全选显示光标。点击屏幕除地址栏其他位置时,键盘隐藏,隐
- C语言 MD5源码md5c.h:/* POINTER defines a generic pointer type */ typedef u
- 一、前言想要自定义starter组件,首先要了解springboot是如何加载starter的,也就是springboot的自动装配机制原理
- 创建类模式主要关注对象的创建过程,将对象的创建过程进行封装,使客户端可以直接得到对象,而不用去关心如何创建对象。创建类模式有5种,分别是:
- 一. 概述: Spinner是我们所熟悉的下拉框列表。与ListView类似,我们必须
- C#中的很多关键词用法比较容易混淆,var和dynamic就是其中一组,他们都可以申明动态类型的变量,但是本质上他们还是有不少区别的。var