1. 总结常见的实现定时任务的几种方法

thread实现 【原理:通过创建一个线程,让他在while循环里面一直运行,用sleep() 方法让其休眠从而达到定时任务的效果。】

Timer类

ScheduledExcecutorService类

使用spring的 spring-task 实现

Quartz

以下演示几种实现方式:每隔一秒打印一次hello world

1.1 thread实现

public static void main(String[] args) {

final long timeInterval = 1000;

Runnable runnable = new Runnable() {

@Override

public void run() {

while (true) {

System.out.println("hello world");

try {

Thread.sleep(timeInterval);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

};

Thread thread = new Thread(runnable);

thread.start();

}

1.2 Timer类实现

Timer是jdk中自带的一个定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次。但封装任务的类是TimerTask类(实际该类是一个抽象类,执行任务的代码要放在该类的子类中)。

TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务。

构造方法:

成员方法:

public static void main(String[] args) {

TimerTask task = new TimerTask() {

@Override

public void run() {

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

}

};

Timer timer = new Timer();

long delay = 0;

long intevalPeriod = 1 * 1000;

timer.scheduleAtFixedRate(task, delay, intevalPeriod);

}

schedule 与 scheduleAtFixedRate区别:

schedule会保证任务的间隔是按照定义的period参数严格执行的,如果某一次调度时间比较长,那么后面的时间会顺延,保证调度间隔都是period。

scheduleAtFixedRate是严格按照调度时间来的,如果某次调度时间太长了,那么会通过缩短间隔的方式保证下一次调度在预定时间执行。

线程安全, 但只会单线程执行, 如果执行时间过长, 就错过下次任务了, 抛出异常时, timerWork会终止

启动和取消任务是可以控制的

1.3 ScheduledExcecutorService类实现

ScheduledExecutorService是JDK1.5以后java.util.concurrent中的一个接口, 用于实现定时任务。

public static void main(String[] args) {

Runnable r1 = new Runnable() {

public void run() {

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

}

};

ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间

service.scheduleAtFixedRate(r1, 3, 1, TimeUnit.SECONDS);// 3秒后开始执行

}

他是通过线程池的方式执行任务,可以多线程执行。

启动和取消任务是可以控制的

可以设定第一次的延迟时间

1.4 使用spring提供的 spring-task 实现

a) 只需要导入web的starter依赖

b) 在启动类上添加 @EnableScheduling 注解

c) 用 @Scheduled 注解开启一个定时任务。

@Component

public class SchedulerTask {

private int count = 0;

/**

* @Author Smith

* @Description 设置每1秒执行一次

* @Date 14:23 2019/1/24

* @Param

* @return void

**/

@Scheduled(cron = "*/1 * * * * ?") // 基于cron表达式实现

private void process(){

System.out.println("hello world " + (count++));

}

}

@Scheduled 该注解的常用参数说明【不基于cron表达式实现的时候】:

fixedRate 表示任务执行之间的时间间隔,具体是指两次任务的开始时间间隔,即第二次任务开始时,第一次任务可能还没结束。

fixedDelay 表示任务执行之间的时间间隔,具体是指本次任务结束到下次任务开始之间的时间间隔。

initialDelay 表示首次任务启动的延迟时间。

所有时间的单位都是毫秒。

1.5 Quartz

参考

源码

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。

Quartz默认是多线程异步执行,单个任务时,在上一个调度未完成时,下一个调度时间到时,会另起一个线程开始新的调度。

Quartz支持集群定时任务

Quartz与Spring Task区别

Quartz默认多线程异步执行,Task默认单线程同步执行。

Quartz单个任务时,在上一个调度未完成时,下一个调度时间到时,会另起一个线程开始新的调度。Task单个任务时,当前次的调度完成后,再执行下一次任务调度。

Quartz多个任务时,任务之间没有直接影响,多任务执行的快慢取决于CPU的性能。Task多个任务时,一个任务执行完成后才会执行下一个任务。若需要任务能够并发执行,需手动设置线程池

Quartz可以采用集群方式,分布式部署到多台机器,分配执行定时任务

两者对比总结:

1、实现,Task注解实现方式,比较简单。Quartz需要手动配置Jobs。

2、任务执行,Task默认单线程串行执行任务,多任务时若某个任务执行时间过长,后续任务会无法及时执行。Quartz采用多线程,无这个问题。

3、调度,Task采用顺序执行,若当前调度占用时间过长,下一个调度无法及时执行;

4、Quartz采用异步,下一个调度时间到达时,会另一个线程执行调度,不会发生阻塞问题,但调度过多时可能导致数据处理异常

5、部署,Quartz可以采用集群方式,分布式部署到多台机器,分配执行定时任务

Quartz 核心概念:

a) Job 表示一个工作,要执行的具体内容。此接口中只有一个方法。Task多个任务时,一个任务执行完成后才会执行下一个任务。若需要任务能够并发执行,需手动设置线程池。

void execute(JobExecutionContext context)

b) JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。

c) Trigger 代表一个调度参数的配置,什么时候去调。

d) Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。

Spring Boot整合Quartz:

导入Quartz依赖

org.springframework.boot

spring-boot-starter-quartz

编写任务类

public class Task implements Job {

// 任务类不能直接注入Bean,若想注入Bean需要配置第4步

@Autowired

private TestService service;

private void before(){

System.out.println("定时任务开始");

}

@Override

public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

service.testDemo();

System.out.println("hello quartz");

}

private void afer(){

System.out.println("定时任务结束");

}

}

★ 任务类不能直接注入Bean,若想注入Bean需要配置第4步 ★

编写Quartz配置

@Configuration

public class QuartzConfig {

@Bean

public JobDetailFactoryBean jobDetailFactoryBean() {

JobDetailFactoryBean factory = new JobDetailFactoryBean();

//关联我们自己的Job类

factory.setJobClass(Task.class);

return factory;

}

@Bean

public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean) {

CronTriggerFactoryBean factory = new CronTriggerFactoryBean();

factory.setJobDetail(jobDetailFactoryBean.getObject());

//设置触发时间

factory.setCronExpression("0/2 * * * * ?");

return factory;

}

@Bean

public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean, MyAdaptableJobFactory jobFactory) {

SchedulerFactoryBean factory = new SchedulerFactoryBean();

//关联trigger

factory.setTriggers(cronTriggerFactoryBean.getObject());

factory.setJobFactory(jobFactory);

return factory;

}

}

编写配置【用于任务类能注入我们的bean】

@Component

public class MyAdaptableJobFactory extends AdaptableJobFactory {

// 可以将一个对象添加到SpringIOC 容器中,并且完成该对象注入

@Autowired

private AutowireCapableBeanFactory autowireCapableBeanFactory;

/**

* 该方法需要将实例化的任务对象手动的添加到springIOC 容器中并且完成对象的注入

*/

@Override

protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {

Object obj = super.createJobInstance(bundle);

//将obj 对象添加Spring IOC 容器中,并完成注入

this.autowireCapableBeanFactory.autowireBean(obj);

return obj;

}

}

2 Quartz[群集环境]

使用quartz实现定时任务[单机版],若是部署多台机器,那么到了时间点,多台服务器便会同时均开始执行定时任务。

Quartz是能适用于分布式集群环境的,在同一时间只会有一台机器执行定时任务。

Quartz 中集群如何工作:

一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。离开了db将无法感知

2.1 导入依赖

org.springframework.boot

spring-boot-starter-quartz

2.2 数据库建表

到官网下载

下载之后解压,进入如下目录,创建数据库表:

11张表功能说明:

java写一个服务定时采集数据_java实现定时任务解决方案相关推荐

  1. java写一个会动的圆_JAVA实现一个圆形的移动,画出来的圆形移动,我的圆它不动呀...

    展开全部 import java.awt.Graphics; import java.awt.Image; import javax.swing.JFrame; public class JoinDe ...

  2. 用java写一个汽车加油的程序_Java实现 LeetCode 134 加油站

    134. 加油站 在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升. 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升 ...

  3. python写一个服务_写一个Python的windows服务

    1. 安装pywin32和pyinstaller pip install pywin32 pip install pyinstaller 2.写一个服务Demo # -*- coding: utf-8 ...

  4. 用java写一个简单的区块链(下)

    用java写一个简单的区块链(下) 2018年03月29日 21:44:35 java派大星 阅读数:725 标签: 区块链java 更多 个人分类: 区块链 版权声明:本文为博主原创文章,转载请标明 ...

  5. java文件客户端下载_使用Java写一个minio的客户端上传下载文件

    标签:color   ati   tty   java   system   wired   format   media   param 前言: 确保已经安装了minio的服务端 代码: pom.x ...

  6. mysql备份到制定目录_写一个脚本定时自动备份mysql到指定目录

    编写一个shell脚本每天16:30备份mysql数据并压缩打包(打包文件按照当天的日期命名)放到/root/data #cd /root #vim mysqlbackup.sh #!/bin/bas ...

  7. python编写数据库连接工具_详解使用Python写一个向数据库填充数据的小工具(推荐)...

    一. 背景 公司又要做一个新项目,是一个合作型项目,我们公司出web展示服务,合作伙伴线下提供展示数据. 而且本次项目是数据统计展示为主要功能,并没有研发对应的数据接入接口,所有展示数据源均来自数据库 ...

  8. 用Java写一个简易五子棋游戏

    一. 程序基本思路: 1.写窗口.棋盘面板.控制面板: 2.绘制棋盘: 3.绘制棋子: 4.添加组件功能: 5.判断输赢: 6.悔棋: 7.复盘. 二.实际操作 1.创建窗口.添加面板 package ...

  9. 用java写一个算工作日期的功能(考虑到节假日以及补班的情况)

    最近公司需要用java写一个算工作日的功能,简单说说我的实现过程跟思路,以供各位参考,大牛勿喷. 基本思路:在数据库先创建一个表,在表中初始化一年中的假期.需要补班等数据(因为每一年放假.补办安排都不 ...

最新文章

  1. insert size|single-read|Paired-end|Mate-pair
  2. TLS与openssl学习总结(三)-实操篇
  3. php字符串常用算法--字符串加密解密
  4. 写底部样式一定要加的属性
  5. 【运维】linux硬盘空间不足,扩容硬盘,挂载目录,并永久挂载
  6. 四级计算机网络考试大纲,2017年全国计算机等级考试四级计算机网络考试大纲...
  7. PHP的魔术常量魔术方法超全局变量
  8. 深度学习基础知识介绍
  9. iBase4J 分布式开发平台
  10. 机器人学导论,课后习题答案。
  11. 摄像头云台的设计,组装与使用方法
  12. vue报错elementUI使用datepicker报错Avoid mutating a prop directly since the value will be overwritten whene
  13. 【小米商城-1 注册功能】
  14. Redis实现点赞功能
  15. 人生的意义是通过努力活得更好
  16. FPGA-炼狱传奇-三态门之战
  17. 学习使用js链接websocket服务断线重连的方法
  18. X86架构与Arm架构区别
  19. 鲲鹏服务器主板销售策略,市场伙伴优先:以行践言,华为鲲鹏做到了
  20. 解码投资浪潮,跨链 DeFi 如何成为下一块淘金地?

热门文章

  1. Manjaro Linux 0.8.5 发布
  2. 任何举动之前,先思考,思考,再思考
  3. 图灵测试是什么?为什么AlphaGo那么牛却过不了?
  4. 6年级学Python,高中学AI?这6本书,助你找回输掉的起跑线
  5. FreeRTOS任务延时函数
  6. Github上都没有的“网约车”项目,终于有人给写出来了!
  7. 一文看懂华为鸿蒙 OS 2.0
  8. Oracle执行外部文件:
  9. 分布式系统中,权限设计实践
  10. OracleExcel VBA写获取表字段类型及约束语句