http://blog.csdn.net/xyang81/article/details/7425943
在日常工作中,定时进行任务调度的业务随处可见,比如:定时清理系统的临时文件、有新的活动定时向用户发送电子邮件、定时检查系统是否需要更新、定时发送短信等业务。在Java中由两个类完成定时任务的调度,分别为:java.util.Timer和java.util.TimerTask
创建一个定时任务的步聚:
1、创建一个定时器(Timer)对象
2、调用该对象的
或schedule(TimerTask task, long delay, long period)
scheduleAtFixedRate(TimerTask task, long delay, long period)
方法
任务调度方法参数说明:
task:表示要执行的具体任务
:表示任务创建完成后,第一次什么时候开始执行该任务,以毫秒为单位delay
period:表示第一次执行完任务后,后续重复执行该任务的时间间隔是多长,以毫秒为单位
schedule方法与
scheduleAtFixedRate方法的区别:
方法 | 任务执行时间 | 当任务执行时间大于间隔时间时 |
schedule | 上次任务的结束时间+时间间隔 | 阻塞式,任务会延后,等待前面的任务执行完,再执行延务后的任务 |
scheduleAtFixedRate | 上次任务的执行时间+时间间隔 | 任务不会延后,但要考虑多线程并发的问题。因为当一个任务还没执行完时,下一个时间间隔任务又会启动,执行相同的任务 |
注意:每启动一个新任务,就会启动一个新的线程!
实例:
- package taskschedule;
- import java.text.SimpleDateFormat;
- import java.util.Calendar;
- import java.util.Timer;
- import java.util.TimerTask;
- /*
- * 定时器
- *
- * schedule():下一次任务的执行时间,等于上一次任务的结束时间+时间间隔
- *
- * scheduleAtFixedRate():下一次任务的执行时间,等于上一次任务的开始时间+时间间隔
- *
- * 当执行任务的时间大于时间间隔时:
- * schedule任务会延后。
- * scheduleAtFixedRate任务不会延后,仍然在时间间隔内执行,存在并发性,要考虑线程同步的问题
- */
- public class TimerTest {
- private static int count = 0;
- public static void main(String[] args) {
- task_1();
- //task_2();
- //task_3();
- //task_4();
- //主线程
- while(true) {
- System.out.println(Calendar.getInstance().get(Calendar.SECOND));
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- //任务1:第一次延迟3秒后启动任务,后续每隔2秒启动一次任务
- private static void task_1() {
- new Timer().schedule(new TimerTask(){
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "定时任务已启动!");
- }}, 3000,2000);
- }
- //任务2:交互执行,方式1:第一次延迟2秒后启动任务,后续每隔在3秒和6秒之间切换启动任务
- private static void task_2() {
- class MyTimerTask extends TimerTask {
- @Override
- public void run() {
- count = (count+1)%2;
- System.out.println(Thread.currentThread().getName() + "定时任务已启动!");
- new Timer().schedule(new MyTimerTask(), 3000 + 3000 * count); //循环调用
- }
- }
- new Timer().schedule(new MyTimerTask(), 2000); //2秒后启动定时器
- }
- //任务3:交互执行,方式2:第一次延迟2秒后启动任务,后续每隔在3秒和6秒之间切换启动任务
- public static void task_3() {
- new Timer().schedule(new MyTimerTaskA(), 300);
- }
- //任务4:演示scheduleAtFixedRate方法,第一次延迟2秒后启动任务,后续每隔3秒后启动任务,但任务执行时间大于等于6秒
- public static void task_4() {
- TimerTask task = new TimerTask(){
- @Override
- public void run() {
- System.out.println("execute task:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));
- try {
- Thread.sleep(6000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "定时任务已启动!");
- }
- };
- new Timer().scheduleAtFixedRate(task, 2000, 3000);
- }
- }
- //描述2个任务切换启动
- class MyTimerTaskA extends TimerTask {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "任务已启动!");
- new Timer().schedule(new MyTimerTaskB(),2000);
- }
- }
- class MyTimerTaskB extends TimerTask {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "任务已启动!");
- new Timer().schedule(new MyTimerTaskA(), 4000);
- }
- }
package taskschedule;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
/*
* 定时器
*
* schedule():下一次任务的执行时间,等于上一次任务的结束时间+时间间隔
*
* scheduleAtFixedRate():下一次任务的执行时间,等于上一次任务的开始时间+时间间隔
*
* 当执行任务的时间大于时间间隔时:
* schedule任务会延后。
* scheduleAtFixedRate任务不会延后,仍然在时间间隔内执行,存在并发性,要考虑线程同步的问题
*/
public class TimerTest {
private static int count = 0;
public static void main(String[] args) {
task_1();
//task_2();
//task_3();
//task_4();
//主线程
while(true) {
System.out.println(Calendar.getInstance().get(Calendar.SECOND));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//任务1:第一次延迟3秒后启动任务,后续每隔2秒启动一次任务
private static void task_1() {
new Timer().schedule(new TimerTask(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "定时任务已启动!");
}}, 3000,2000);
}
//任务2:交互执行,方式1:第一次延迟2秒后启动任务,后续每隔在3秒和6秒之间切换启动任务
private static void task_2() {
class MyTimerTask extends TimerTask {
@Override
public void run() {
count = (count+1)%2;
System.out.println(Thread.currentThread().getName() + "定时任务已启动!");
new Timer().schedule(new MyTimerTask(), 3000 + 3000 * count); //循环调用
}
}
new Timer().schedule(new MyTimerTask(), 2000); //2秒后启动定时器
}
//任务3:交互执行,方式2:第一次延迟2秒后启动任务,后续每隔在3秒和6秒之间切换启动任务
public static void task_3() {
new Timer().schedule(new MyTimerTaskA(), 300);
}
//任务4:演示scheduleAtFixedRate方法,第一次延迟2秒后启动任务,后续每隔3秒后启动任务,但任务执行时间大于等于6秒
public static void task_4() {
TimerTask task = new TimerTask(){
@Override
public void run() {
System.out.println("execute task:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "定时任务已启动!");
}
};
new Timer().scheduleAtFixedRate(task, 2000, 3000);
}
}
//描述2个任务切换启动
class MyTimerTaskA extends TimerTask {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "任务已启动!");
new Timer().schedule(new MyTimerTaskB(),2000);
}
}
class MyTimerTaskB extends TimerTask {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "任务已启动!");
new Timer().schedule(new MyTimerTaskA(), 4000);
}
}
任务执行结果:
任务1:
任务2:
任务3:
任务4:
但JDK提供的定时器任务功能有限,不能完成一些复杂的业务,比如:要每年单月的每周星期三的下午5点10分要执行一个任务,JDK则处理不了。不过不要担心,市面上已经有开源的任务调度框架:Quartz,官网:http://www.quartz-scheduler.org/