实现定时任务的 6 种方式,一网打尽!
实现定时任务有6种方式:
- 使用线程创建定时任务
- 使用
TimerTask
创建定时任务 - 使用线程池创建定时任务
- 使用
Quartz
框架实现定时任务 - 使用
@Scheduled
注解实现定时任务 xxl-job
实现分布式定时任务
一、使用线程创建定时任务
public class ThreadTask {
public static class Demo01 {
static long count = 0;
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
count++;
System.out.println(count);
} catch (Exception e) {
// TODO: handle exception
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
}
二、使用TimerTask创建定时任务
public class Timer4Task {
static long count = 0;
public static void main(String[] args) {
TimerTask timer4Task = new TimerTask() {
@Override
public void run() {
count++;
System.out.println(count);
}
};
//创建timer对象设置间隔时间
Timer timer = new Timer();
// 间隔天数
long delay = 0;
// 间隔毫秒数
long period = 1000;
timer.scheduleAtFixedRate(timer4Task, delay, period);
}
}
三、使用线程池创建定时任务
public class ThreadPoolTask {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
// task to run goes here
System.out.println("Hello !!");
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service.scheduleAtFixedRate(runnable, 1, 1, TimeUnit.SECONDS);
}
}
四、使用Quartz框架实现定时任务
Quartz /kwɔːrts/
public class QuartzTask {
public static void main(String[] args) throws SchedulerException {
//1.创建Scheduler的工厂
SchedulerFactory sf = new StdSchedulerFactory();
//2.从工厂中获取调度器实例
Scheduler scheduler = sf.getScheduler();
//3.创建JobDetail,
JobDetail jb = JobBuilder.newJob(SelfJob.class)
//job的描述
.withDescription("this is a ram job")
//job 的name和group
.withIdentity("ramJob", "ramGroup")
.build();
//任务运行的时间,SimpleSchedle类型触发器有效,3秒后启动任务
long time = System.currentTimeMillis() + 3 * 1000L;
Date statTime = new Date(time);
//4.创建Trigger
//使用SimpleScheduleBuilder或者CronScheduleBuilder
Trigger t = TriggerBuilder.newTrigger()
.withDescription("")
.withIdentity("ramTrigger", "ramTriggerGroup")
//.withSchedule(SimpleScheduleBuilder.simpleSchedule())
//默认当前时间启动
.startAt(statTime)
//两秒执行一次,Quartz表达式,支持各种牛逼表达式
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
.build();
//5.注册任务和定时器
scheduler.scheduleJob(jb, t);
//6.启动 调度器
scheduler.start();
}
}
/**
* 继承Quartz框架中的Job,并重写execute方法
*/
public class SelfJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("quartz Job date:" + System.currentTimeMillis());
}
}
五、使用 @Scheduled 注解实现定时任务
@Configuration // 这里使用@Component也行
public class ScheduleTask {
//添加定时任务-- 50分钟执行一次
@Scheduled(fixedRate = 50 * 60 * 1000)
private void updateTask() {
Console.log("@Scheduled 注解实现定时任务 执行-------------------");
}
}
启动类增加 @EnableScheduling
注解,启动服务。
六、使用 xxl-job 实现分布式定时任务
6.1 引入依赖
项目中引入下面的依赖:
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.2.0</version>
</dependency>
6.2 配置文件增加配置
xxl:
job:
accessToken:
executor:
appname: demo
ip:
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: -1
port: 9966
admin:
# addresses: http://127.0.0.1:8089/xxl-job-admin
addresses: http://49.234.28.149:8086/xxl-job-admin
6.3 任务接口
@Component
@Slf4j
@RequiredArgsConstructor
public class XxlJobHandler{
@XxlJob("demoHandler")
public ReturnT<Object> run (Object s) throws Exception {
XxlJobLogger.log("xxl-job测试任务开始执行。【args: {}】", s);
try {
System.out.println("执行一次xxl-job打印任务!");
XxlJobLogger.log("xxl-job测试任务执行结束。");
return null;
} catch (Exception e) {
XxlJobLogger.log("xxl-job测试任务执行出错!", e);
return null;
}
}
}
或者这样写也行:
@JobHandler(value="demoHandler")
@Component
public class DemoJobHandler extends IJobHandler {
static int count;
@Override
public ReturnT<String> execute(String param) throws Exception {
System.out.println("执行job任务"+count++);
return SUCCESS;
}
}
6.4 下载并启动 xxl-job
下载地址:https://github.com/xuxueli/xxl-job/
找到 xxl-job-admin
模块,初始化数据库并配置数据库资源、端口等,最后启动服务。
启动后在浏览器输入: http://localhost:8061/xxl-job-admin ,进入 xxl-job
管理后台:
添加好执行器,再新建一个任务:
启动服务后会每5秒执行一次,可以根据需求自定义执行时间和周期。
或者
七、总结
前5种定时任务方式可以归为一派,原因是这5个方式都是只适用于单实例部署,若是多实例部署那就会重复执行。比如有个定时任务是每天早上8点执行,而你部署了2个实例,那在8点的时候就会执行两遍。
这前5种方式中,使用 @Scheduled
注解最简单,更方便。
xxl-job
的方式,就是在布式集群的情况下,保证定时任务不被重复执行。执行原理同Nginx 类型,所有定时任务通过任务调度平台分发,也可配置负载均衡等。其中的时间表达式可以很灵活,可以自行搜索。