勿以恶小而为之,勿以善小而不为--------------------------刘备
劝诸君,多行善事积福报,莫作恶
上一章简单介绍了 JavaSE实现国际化操作(十五),如果没有看过,请观看上一章
一. 为什么要出现定时任务?
在实际生活和开发中,常常会遇到类似的情况, 如 1.女朋友生日那一天,发送定时消息,提醒生日快乐 2. 给某人写邮件编写好内容之后,在晚上10点时准时发送, 3 某天固定8点起床,晚上10点睡觉 4.母亲节,父亲节时给父母发送消息。 等生活中的定时小例子 (闹钟,备忘录都属于定时)。
开发中,1. 给已经注册的用户,在用户生日那天,发送生日祝福. 2. 公司员工,当入职满一年时,增加年假至5天,入职5年时,增加年假至10天。 3.定时删除三个月前的日志记录消息。 4. 定时监测网站访问情况等开发中的定时小例子。
这些生活和开发实例,都属于定时任务。 定时任务,是很常见的,也是很重要的。
JavaSE 阶段提供了 三种方式,来实现定时任务。
JavaEE 阶段,使用 Quartz 框架来实现定时任务。
二. JavaSE 阶段实现定时任务
二.一 多线程 Runnable 和Thread 实现定时任务
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* Thread 多线程通过休眠时间来实现定时执行
* @author 两个蝴蝶飞
*
*/
public class ThreadDemo {
public static void main(String []args){
//定时的时间
Long SLEEP_TIME=1000*5L;
Runnable runnable=new Runnable() {
@Override
public void run() {
while(true){
try {
//通过设置休眠,来达到定时的效果。 每5s执行一次
Thread.sleep(SLEEP_TIME);
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String localeDate=sdf.format(new Date());
System.out.println("Thread 线程:当前时间为:"+localeDate);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
};
Thread thread=new Thread(runnable);
thread.start();
}
}
控制台打印输出:
如果想取消定时的话, 可以定义一个全局常量flag,flag默认是true, 将 while(true) 改成 while(flag), 当取消定时时,将flag 由true 改成false 即可。
二.二 TimerTask 和 Timer 实现定时任务
二.二.一 代码编写
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
*
* TimerTask 和Timer 实现定时任务
* @author 两个蝴蝶飞
*
*/
public class TaskDemo {
public static void main(String[] args) {
Timer timer=new Timer();
TimerTask task=new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String localeDate=sdf.format(new Date());
System.out.println("Task任务:当前时间为:"+localeDate);
}
};
timer.scheduleAtFixedRate(task,0,5000);
//调用 cancel()方法来取消定时
//timer.cancel();
}
}
通过调用 Timer 对象的 scheduleAtFixedRate() 方法,来实现定时任务。
控制台打印输出:
二.二.二 Timer中的调度方法
task 均为执行定时任务的对象,时间单位为 ms.
方法签名 | 作用 |
---|---|
schedule(TimerTask task, long delay) | 在delay ms 后执行定时任务,只执行一次 |
schedule(TimerTask task, Date time) | 在time 时间时执行定时任务,只执行一次 |
public void schedule(TimerTask task, long delay, long period) | 在delay ms后执行定时任务, 并且每隔 period 毫秒再次执行任务,会多次执行, 以固定时间 |
schedule(TimerTask task, Date firstTime, long period) | 在firstTime时间执行定时任务, 并且每隔 period毫秒再次执行任务,会多次执行, 以固定时间 |
scheduleAtFixedRate(TimerTask task, long delay, long period) | 在delay ms后执行定时任务, 并且每隔 period 毫秒再次执行任务,会多次执行, 不一定均以固定时间执行 |
scheduleAtFixedRate(TimerTask task, Date firstTime, long period) | 在firstTime时间执行定时任务, 并且每隔 period毫秒再次执行任务,会多次执行, 不一定均以固定时间执行 |
schedule()方法和 scheduleAtFixedRate()方法,是有一些区别的。
schedule()方法,假设是每5s执行一次,由5s,10s,15s,20s时执行, 但由于CPU征用导致定时任务并没有在5s这个时间上执行,而是在9s时执行了,延迟了4s,那么下一次该任务执行的时间是 9+5=14s,而不是原计划的10s. 这样会导致可能漏掉调度的情况。
scheduleAtFixedRate()方法,假设是每5s执行一次,由5s,10s,15s,20s时执行, 但由于CPU征用导致定时任务并没有在5s这个时间上执行,而是在9s时执行了,延迟了4s,那么下一次该任务执行的时间还是10s, 与原计划一样(会将间隔时间的period=5000 变成period=1000,但下下一次仍然是5000), 不会导致漏掉调度的情况。
故常常使用的是 scheduleAtFixedRate() 方法。
二.三 ScheduledExecutor 实现定时任务
在 java.util.concurrent 包下
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* ScheduledExecutor 实现定时调度
* @author 两个蝴蝶飞
*
*/
public class ScheduleDemo {
public static void main(String[] args) {
//定义定时任务
Runnable runnable=new Runnable() {
@Override
public void run() {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String localeDate=sdf.format(new Date());
System.out.println("Scheduled调度:当前时间为:"+localeDate);
}
};
//定义调度服务
ScheduledExecutorService scheduledExecutorService=Executors.newSingleThreadScheduledExecutor();
//运行, 哪个任务,开始时间,间隔时间,间隔单位
scheduledExecutorService.scheduleAtFixedRate(runnable, 0, 2, TimeUnit.SECONDS);
}
}
控制台打印输出:
三. JavaSE 实现调度的不足
上面的三种方式,虽然都实现了定时任务,但面对复杂多变的定时任务情况,就显得力不从心了。
如,
-
无法实现类似 ‘每年的母亲节给母亲发送祝福’,‘每个月的最后一天显示员工的本月的工作情况’,‘距离每个月10号最近的工作日发薪资’ 等非固定日期的情况。开发者不能在程序中进行判断日期。
-
无法与当前主流框架 Spring 进行很好的整合。
-
定时任务的事务处理,需要开发者自己进行处理。
-
定时任务持久化保存
想处理好定时任务,可以学习一下 Quartz 定时任务框架。
谢谢您的观看!!!