java定时qu,Java 定时任务 & 任务调度

更多 Java 高级知识方面的文章,请参见文集《Java 高级知识》

任务调度是指基于 给定时间点,给定时间间隔 或者 给定执行次数 自动执行任务。

方式1:通过 Thread 来实现

例如如下的代码,可以每隔 1000 毫秒做一次打印操作。

public class Job_Schedule_Test1 {

public static void main(String[] args) {

new JobThread().start();

}

}

class JobThread extends Thread {

public void run() {

while (true) {

System.out.println("Test: " + Calendar.getInstance().getTime());

try {

Thread.sleep(1000);

} catch (Exception e) {

}

}

}

}

输出如下:

Test: Wed Feb 22 14:33:57 CST 2017

Test: Wed Feb 22 14:33:58 CST 2017

Test: Wed Feb 22 14:33:59 CST 2017

Test: Wed Feb 22 14:34:00 CST 2017

Test: Wed Feb 22 14:34:01 CST 2017

方式2:通过 Timer 来实现

自定义一个任务,继承于 TimerTask,重写 run 方法

利用 java.util.Timer 实现任务调度

public class Job_Schedule_Test2 {

public static void main(String[] args) {

Timer timer = new Timer();

long delay = 2000;

long interval = 1000;

// 从现在开始 2 秒钟之后启动,每隔 1 秒钟执行一次

timer.schedule(new JobTask(), delay, interval);

}

}

class JobTask extends TimerTask {

public void run() {

System.out.println("Test: " + Calendar.getInstance().getTime());

}

}

输出如下:

Test: Wed Feb 22 15:02:15 CST 2017

Test: Wed Feb 22 15:02:16 CST 2017

Test: Wed Feb 22 15:02:17 CST 2017

Test: Wed Feb 22 15:02:18 CST 2017

Test: Wed Feb 22 15:02:19 CST 2017

Timer 的设计核心是一个 TaskList 和一个 TaskThread。

Timer 将接收到的任务丢到自己的 TaskList 中,TaskList 按照 Task 的最初执行时间进行排序。TimerThread 在创建 Timer 时会启动成为一个守护线程。这个线程会轮询所有任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread 被唤醒并执行该任务。之后 TimerThread 更新最近一个要执行的任务,继续休眠。

Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。

例如我们指定每隔 1000 毫秒执行一次任务,但是可能某个任务执行花了 5000 毫秒,因此导致后续的任务并不能按时启动执行。

方式3:通过 ScheduledExecutorService 来实现

鉴于 Timer 的上述缺陷,Java 5 推出了基于线程池设计的 ScheduledExecutorService。

其设计思想是,每一个被调度的任务都会 由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。

需要注意的是,只有当任务的执行时间到来时,ScheduledExecutorService 才会真正启动一个线程,其余时间 ScheduledExecutorService 都是在轮询任务的状态。

public class Job_Schedule_Test3 {

public static void main(String[] args) {

ScheduledExecutorService service = Executors.newScheduledThreadPool(10);

long delay = 2;

long interval = 1;

// 从现在开始 2 秒钟之后启动,每隔 1 秒钟执行一次

service.scheduleAtFixedRate(

new JobTask2(), delay,

interval, TimeUnit.SECONDS);

}

}

class JobTask2 implements Runnable {

public void run() {

System.out.println("Test: " + Calendar.getInstance().getTime());

}

}

输出如下:

Test: Wed Feb 22 15:19:05 CST 2017

Test: Wed Feb 22 15:19:06 CST 2017

Test: Wed Feb 22 15:19:07 CST 2017

Test: Wed Feb 22 15:19:08 CST 2017

Test: Wed Feb 22 15:19:09 CST 2017

用 ScheduledExecutorService 和 Calendar 实现复杂任务调度

Timer和 ScheduledExecutor 都仅能提供基于开始时间与重复间隔的任务调度,不能胜任更加复杂的调度需求。

比如,设置每星期二的 16:38:10 执行任务。我们可以借助 Calendar 间接实现该功能。

其核心在于根据当前时间推算出最近一个星期二 16:38:10 的绝对时间,然后计算与当前时间的时间差,作为调用 ScheduledExceutor 函数的参数。

方式4:通过 Quartz 来实现

Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do.

示例如下:

public class QuartzJob implements org.quartz.Job {

public QuartzJob() {

}

public void execute(JobExecutionContext arg0) throws JobExecutionException {

System.out.println("Test: " + Calendar.getInstance().getTime());

}

}

import org.quartz.*;

import org.quartz.impl.StdSchedulerFactory;

import static org.quartz.JobBuilder.*;

import static org.quartz.TriggerBuilder.*;

import static org.quartz.SimpleScheduleBuilder.*;

public class Job_Schedule_Test4 {

public static void main(String[] args) throws SchedulerException {

// Grab the Scheduler instance from the Factory

Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

// define the job and tie it to our MyJob class

JobDetail job = newJob(QuartzJob.class)

.withIdentity("job1", "group1")

.build();

// Trigger the job to run now, and then repeat every 40 seconds

Trigger trigger = newTrigger()

.withIdentity("trigger1", "group1")

.startNow()

.withSchedule(simpleSchedule()

.withIntervalInSeconds(1)

.repeatForever())

.build();

// Tell quartz to schedule the job using our trigger

scheduler.scheduleJob(job, trigger);

// and start it off

scheduler.start();

}

}

方式5:通过 JCronTab 来实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值