本文列举常见的java定时任务实现方式,并做一定比较。

1. 循环内部sleep实现周期执行

创建一个thread,run() while循环里sleep()来实现周期性执行; 简单粗暴,作为一个初学者很容易想到。

public class Task1 {

public static void main(String[] args) {

// run in a second

final long timeInterval = 1000;

Runnable runnable = new Runnable() {

public void run() {

while (true) {

System.out.println("Hello !!");

// 使用线程休眠来实现周期执行,

try {

Thread.sleep(timeInterval);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

};

Thread thread = new Thread(runnable);

thread.start();

}

}

2. 使用Timer类调度TimerTask任务

改进:当启动和去取消任务时可以控制; 第一次执行任务时可以指定你想要的delay时间

不足:

Timer的调度是基于绝对时间的,所以当系统时间改变时会影响Timer。

Timer只有一个工作线程,所以当一个任务执行时间很长的时候,会影响后续任务的调度。

而ScheduledThreadPoolExecutor通过线程池的方式配置更灵活。

如果任务抛出了一个未检查的异常,将会导致Timer的工作线程被终止,使Timer无法在继续运行。

import java.util.Timer;

import java.util.TimerTask;

public class HelperTest {

public static void main(String[] args) {

// 具体任务。

TimerTask task = new TimerTask() {

@Override

public void run() {

// task to run goes here

System.out.println("Hello !!!");

}

};

// Timer类可以调度任务。 Timer实例可以调度多任务,它是线程安全的。

Timer timer = new Timer();

long delay = 0;

long intevalPeriod = 1 * 1000;

// schedules the task to be run in an interval

timer.scheduleAtFixedRate(task, delay, intevalPeriod);

}

}

3. 使用j.u.c.ScheduledExecutorService定时任务接口

相比于Timer的单线程,它是通过线程池的方式来执行任务的

可以灵活的设定第一次执行任务delay时间

提供了良好的约定,以便设定执行的时间间隔

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class Task3 {

public static void main(String[] args) {

ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);

// 初始化延迟0ms开始执行,每隔200ms重新执行一次任务。

ScheduledExecutorService pool = new ScheduledThreadPoolExecutor(1);

pool.scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

// task to run goes here

System.out.println("Hello !");

}

}, 0, 200L, TimeUnit.MILLISECONDS);

}

实现类使用的是ScheduledThreadPoolExecutor。该类继承自ThreadPoolExecutor read more,阻塞队列使用的是DelayedWorkQueue,是ScheduledThreadPoolExecutor的内部类。

ScheduledExecutorService接口方法说明:

其中scheduleAtFixedRate和scheduleWithFixedDelay在实现定时程序时比较方便。

scheduleAtFixedRate(runnable, 0, 200L, TimeUnit.MILLISECONDS) 按指定周期执行某个任务

初始化延迟0ms开始执行,每隔200ms重新执行一次任务。

scheduleWithFixedDelay(runnable, 0, 200L, TimeUnit.MILLISECONDS) 按指定间隔执行某个任务

初始化时延时0ms开始执行,下次执行时间是(本次执行结束 + 延迟200ms)后开始执行。

schedule(Runnable command, long delay, TimeUnit unit) 在delay延时后执行一次性任务

备注:对于scheduleAtFixedRate,实际上如果当前线程阻塞执行时间t > 设置的间隔时间period,下次是在t时间后执行,并非period时间后立即开始。

ScheduledExecutorService的spring配置

>> spring.xml

>> xxx.java

@Autowired

@Qualifier("gkHeartBeatScheduler")

ScheduledExecutorService scheduledExecutorService;

scheduledExecutorService.scheduleAtFixedRate(

new Runnable() {

@Override

public void run() {

System.out.println("do sth");

}

}, 1l, 2l, TimeUnit.SECONDS);

spring ScheduledExecutorFactoryBean内部同样使用的ScheduledThreadPoolExecutor,并对其做了包装处理。

public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport implements FactoryBean

4. @Sheduled注解方式

@Sheduled内部也使用了ScheduledThreadPoolExecutor。具体源代码可参见:spring-context包中的ScheduledAnnotationBeanPostProcessor。

用法就很简单了,举例:

pom文件引入spring-context依赖

使用注解方式配置定时任务即可

import org.springframework.scheduling.annotation.EnableScheduling;

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Component;

@Component

@EnableScheduling

public class ScheduledAnnotationDemo {

// @Scheduled和触发器元素一起添加到方法上.

@Scheduled(fixedDelay=5000)

public void doSomething() {

System.out.println("like scheduleWithFixedDelay");

}

@Scheduled(fixedRate=5000)

public void doSomething() {

System.out.println("like scheduleAtFixedRate");

}

// fixed-delay、fixed-rate任务都可以设置初始delay。

@Scheduled(initialDelay=1000, fixedRate=5000)

public void doSomething() {

// something that should execute periodically

}

// 也支持cron表达式

@Scheduled(cron = "0/5 * * * * ?")

public void doSomething() {

// something that should execute on weekdays only

System.out.println("5s执行一次");

}

//cron举例:(秒 - 分 - 时 - 日 - 月- 星期)

// */5 * * * * ? 每隔5秒执行一次

// 0 */1 * * * ? 每隔1分钟执行一次

// 0 0 1 * * ? 每天1点执行一次

// 0 0 1 1 * ? 每月1号1点执行一次

// 0 0 1 L * ? 每月最后一天1点执行一次

// 0 0 1 ? * L 每周星期天1点执行一次

}

上面使用@EnableScheduling的方式启动定时任务,等价于在spring xml中配置元素。

5. 开源任务调度框架Quartz

Quartz , 功能强大的任务调度库。适用于具有更复杂调度要求的场景。

提供了对持久化任务调度信息、事务、分布式的支持。与spring无缝对接。

6. 小结

使用ScheduledThreadPoolExecutor完成简单定时任务,是比较理想和常用的实现方式。书写时更容易理解其过程实现。

也可以用@Sheduled注解的形式,更加轻量化,看起来更简洁。

对复杂的任务调度,可以使用Quartz框架。

java实现周期任务_java定时任务的实现方式相关推荐

  1. java文件定时读写_java定时任务及日志的使用

    需要引入日志的两个架包: log4j.jar和commons-logging.jar package com.lzl; import java.util.TimerTask; import org.a ...

  2. java的rsa作用_java 中RSA的方式实现非对称加密的实例

    java 中rsa的方式实现非对称加密的实例 rsa通俗理解: 你只要去想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密:同理,既然是签名,那肯 ...

  3. java两二叉树相同_java – 最有效的方式来测试两个二叉树的相等性

    您将如何在Java中实现二叉树节点类和二叉树类以支持最有效(从运行时角度)相等的检查方法(也必须实现): boolean equal(Node root1, Node root2) {} 要么 boo ...

  4. java反射效率对比_Java反射三种方式的效率对比

    1 使用field long start = System.nanoTime(); Field[] fields = CallCount.class.getDeclaredFields(); for ...

  5. JAVA解决生产消费者_Java常用三种方式解决生产者消费者问题(详细)

    package test; /** * Synchronized 版本解决生产者消费者 * wait() / notify()方法 */ import java.util.LinkedList; im ...

  6. java 向上抛异常_Java 异常的处理方式throws

    在昨天的文章<Java 异常的分类与处理>中我们简单地了解了一下在方法声明的位置上使用throws关键字向上抛出异常,下面深入讲解异常的第一种处理方式throws. 下面深入讲解异常的第一 ...

  7. java数据加密解密代码_java使用RSA加密方式实现数据加密解密的代码

    RSA的应用 RSA是一种非对称加密算法.现在,很多登陆表单的密码的都采用RSA加密,例如京东中的登陆使用公钥对密码进行加密 java使用RSA加密方式实现数据加密解密,需要首先产生私钥和公钥 测试代 ...

  8. java http请求实现_JAVA实现HTTP请求方式

    get请求 public String sendGet(String httpurl) throws IOException { URL url = new URL(httpurl); HttpURL ...

  9. java ftp传图片_Java 图片上传方式一 : ftp 图片服务器

    一 : Linux ftp 图片服务器 1. Linux 安装 ftp linux服务器配置 安装ftp yum install vsftpd 启动服务 service vsftpd start 开机 ...

最新文章

  1. 看初中生如何高薪就业
  2. python - 栈与队列(只有代码)
  3. MySQL 4.1/5.0/5.1/5.5各版本的主要区别
  4. 报错解决方法1:‘A GDAL API version must be specified.’
  5. Linux-diff和diff3命令
  6. centos7下安装低版本mysql_centos7下使用yum安装制定版本mysql
  7. winform直接控制云台_速学指南,2分钟学会Feiyu pocket口袋云台的隐藏功能操作
  8. 从Java到Go面向对象--继承思想.md
  9. linq to entity 左联接 右连接 以及内连接写法的区别(转)
  10. premnmx tramnmx postmnmx 函数用法
  11. 微软Power Platform在中国市场正式商用 无缝衔接微软智能云“三驾马车”
  12. 4个基本不等式的公式高中_基本不等式公式四个
  13. 微软文件共享服务器进程,Windows Server“8”– 将服务器应用程序存储转移到 Windows 文件共享...
  14. 随笔--初到青岛,爱意油然而生
  15. SCI三区论文大修笔记(已录用)
  16. 将数字编号翻译为英文编号(python)实现
  17. 2022最新MN梦奈宝塔主机系统V1.5版本+UI不错
  18. 不在乎 -- 陆琪
  19. 过滤器以及Severlet 的实例
  20. Taro小程序,底部输入框获取键盘高度动态设置bottom有延迟解决

热门文章

  1. Matlab矩阵查找
  2. 6个步骤卸载wine
  3. linux如何获取raw中的文件路径,如何使用Linux获取Touchscreen Rawdata的坐标
  4. mysql自增id用完了_MySQL表自增id用完了该怎么办?
  5. 【APICloud系列|38】 微信登录分享、QQ登录分享实现方法
  6. 早上起来CSDN的PC端主页积分变成了0
  7. mysql、oracle知识点总结
  8. mysql 更改root密码字段不存在_初次登陆MySQL修改密码是出现Unknown column 'password' in 'field list'的解决方法...
  9. 为自己写程序之JavsScript代码段测试器
  10. CSS揭秘(二)背景与边框