java写一个服务定时采集数据_java实现定时任务解决方案
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实现定时任务解决方案相关推荐
- java写一个会动的圆_JAVA实现一个圆形的移动,画出来的圆形移动,我的圆它不动呀...
展开全部 import java.awt.Graphics; import java.awt.Image; import javax.swing.JFrame; public class JoinDe ...
- 用java写一个汽车加油的程序_Java实现 LeetCode 134 加油站
134. 加油站 在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升. 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升 ...
- python写一个服务_写一个Python的windows服务
1. 安装pywin32和pyinstaller pip install pywin32 pip install pyinstaller 2.写一个服务Demo # -*- coding: utf-8 ...
- 用java写一个简单的区块链(下)
用java写一个简单的区块链(下) 2018年03月29日 21:44:35 java派大星 阅读数:725 标签: 区块链java 更多 个人分类: 区块链 版权声明:本文为博主原创文章,转载请标明 ...
- java文件客户端下载_使用Java写一个minio的客户端上传下载文件
标签:color ati tty java system wired format media param 前言: 确保已经安装了minio的服务端 代码: pom.x ...
- mysql备份到制定目录_写一个脚本定时自动备份mysql到指定目录
编写一个shell脚本每天16:30备份mysql数据并压缩打包(打包文件按照当天的日期命名)放到/root/data #cd /root #vim mysqlbackup.sh #!/bin/bas ...
- python编写数据库连接工具_详解使用Python写一个向数据库填充数据的小工具(推荐)...
一. 背景 公司又要做一个新项目,是一个合作型项目,我们公司出web展示服务,合作伙伴线下提供展示数据. 而且本次项目是数据统计展示为主要功能,并没有研发对应的数据接入接口,所有展示数据源均来自数据库 ...
- 用Java写一个简易五子棋游戏
一. 程序基本思路: 1.写窗口.棋盘面板.控制面板: 2.绘制棋盘: 3.绘制棋子: 4.添加组件功能: 5.判断输赢: 6.悔棋: 7.复盘. 二.实际操作 1.创建窗口.添加面板 package ...
- 用java写一个算工作日期的功能(考虑到节假日以及补班的情况)
最近公司需要用java写一个算工作日的功能,简单说说我的实现过程跟思路,以供各位参考,大牛勿喷. 基本思路:在数据库先创建一个表,在表中初始化一年中的假期.需要补班等数据(因为每一年放假.补办安排都不 ...
最新文章
- insert size|single-read|Paired-end|Mate-pair
- TLS与openssl学习总结(三)-实操篇
- php字符串常用算法--字符串加密解密
- 写底部样式一定要加的属性
- 【运维】linux硬盘空间不足,扩容硬盘,挂载目录,并永久挂载
- 四级计算机网络考试大纲,2017年全国计算机等级考试四级计算机网络考试大纲...
- PHP的魔术常量魔术方法超全局变量
- 深度学习基础知识介绍
- iBase4J 分布式开发平台
- 机器人学导论,课后习题答案。
- 摄像头云台的设计,组装与使用方法
- vue报错elementUI使用datepicker报错Avoid mutating a prop directly since the value will be overwritten whene
- 【小米商城-1 注册功能】
- Redis实现点赞功能
- 人生的意义是通过努力活得更好
- FPGA-炼狱传奇-三态门之战
- 学习使用js链接websocket服务断线重连的方法
- X86架构与Arm架构区别
- 鲲鹏服务器主板销售策略,市场伙伴优先:以行践言,华为鲲鹏做到了
- 解码投资浪潮,跨链 DeFi 如何成为下一块淘金地?