java中的定时任务
在文章的开头,我们先来了解一些定时任务的概念,定时任务表示的是在规定的时间开始执行一定的任务,这理解起来也是比较通俗易懂的,下面我们来介绍一下java中为我们提供的定时任务的实现。
1、Timer和TimerTake
2、ScheduledExecutorService
3、第三方的Quartz框架。
Timer和TimerTask
Timer和TimerTask是java.util包下为我们提供的定时任务调度类,下面通过一个简单的列子来了解它的使用。
public static void main(String[] args) {
//获取一个单线程的调度器Timer类
Timer timer=new Timer();
//生成一个TimerTask任务并自定义任务,重写run方法,第二个参数为延迟
//执行时间,第三个为重复执行时间间隔
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("lau 的博客");
}
},1000,2000);
}
首先创建一个Timer类,然后创建TimerTask任务,其实TimerTask继承了Runable接口,抽象描述一种任务,我们只要实现其run方法就可以对任务的自定义。
我们来看一些Timer类,
在该类中,TaskQueue是一个用于保存任务的任务队列,他是按照优先级进行排序的,越先执行的优先级越高,
TimerThread是Timer的一个的一个内部类,它重写了Thread的run方法,该线程实例将会在Timer类被创建时被启动。
通过设置线程名创建Timer实例。
下面我们来看一下Timer类中的Shcedule都有哪些重载的类型。
其中task为自定义任务,delay为你定时任务开始的时间加上delay的时间,period为自定义任务启动后每次重复执行的间隔时间。
最后,我们看一看这个 Timer 它有哪些劣势的地方:
Timer 的背后只有一个线程,不管你有多少个任务,都只有一个工作线程,效率上必然是要打折扣的。
限于单线程,如果第一个任务逻辑上死循环了,后续的任务一个都得不到执行。 依然是由于单线程,任一任务抛出异常后,整个 Timer
就会结束,后续任务全部都无法执行。
ScheduledExecutorService
介绍完了Timer和TimerTask实现定时任务,我们来介绍ScheduledExecutorService
ScheduledExecutorService是线程池,而Timer是单线程模式,ScheduledExecutorService有三个用法,如下
实现程序如下:
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个线程池的多线程调度服务,8为线程数量
ScheduledExecutorService service= Executors.newScheduledThreadPool(8);
//
ScheduledFuture<?> future=service.scheduleWithFixedDelay(new Thread(){
@Override
public void run() {
System.out.println("nihao");
}
},3,1, TimeUnit.SECONDS);
}
对于scheduleWithFilxedDelay而言:
假如我们设置的间隔1秒,任务要耗时3秒,两个时间相加正好是4秒,那么之前代码注释的解释就说的通了:以上一次任务的结束时间 + 延迟时间 = 下一次任务的开始时间。
对于scheduleWithFilxedRate而言:
也就是以上一个任务的开始时间 + 延迟时间 = 下一个任务的开始时间。
第三方的Quartz框架。
首先导入相应的jar包:
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz-jobs -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.2</version>
</dependency>
创建相应的类,实现Job类并重写execute方法作为自定义任务
编写相应的程序:
public static void main(String[] args) throws SchedulerException {
//创建一个调度器生成工产
StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
//获取一个调度器
Scheduler scheduler = stdSchedulerFactory.getScheduler();
//创建一个定时任务
JobDetail job = JobBuilder.newJob(Myjob.class)
.withIdentity("xx", "xxx").build();
//定义定时任务触发器
Trigger trigger= TriggerBuilder.newTrigger().withIdentity("bb", "bbb")
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withRepeatCount(8))
.startNow().build();
//将定时任务和触发器加入调度
scheduler.scheduleJob(job, trigger);
//开始
scheduler.start();
}
//Myjob.java
package quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class Myjob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("hello world");
}
}
用quartz框架实现定时任务的步骤:
- 首先导入相应需要的jar包
- 编写任务类实现Job接口重写execute方法
- 通过调度器工产获取调度器
- 编写job任务实例和触发器实例
- 对任务进行调度并且启动调度器