Timer是jdk中提供的一个定时器工具,使用的时候会在主线程之外另起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次。
TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务。
package com.dswh.test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(task, 0, 3000);
}
static TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("每3s执行一次");
}
};
}
执行效果:定时每3秒执行一次任务
取消定时任务只需再调用一次timer.cancel();即可取消任务调度。
package com.dswh.test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) throws Exception {
Timer timer = new Timer();
timer.schedule(task, 0, 2000);
Thread.sleep(10000);
//取消定时任务
timer.cancel();
System.out.println("定时任務已取消");
}
static TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("每3s执行一次");
}
};
}
3.1问题的原因
当我们使用task.cancel()或者timer..cancel()来取消定时任务后再调用原来的定时任务时,可能会出现这两种错误,原因是因为每个task都是一次性的消耗品,当使用cancel方法后,这个task就被消耗掉了,想要再次使用就只能再次创建新的task,timer也是如此。如下:
3.2 多任务调度
方式一:
如果有多个定时task要执行,我们可以提供继承TimerTask来分别定义两个task的方法实现。当想要取消某个task,使用task.cancel()来取消指定task,可以将timer设置为全局变量,所有task共用一个timer。
task1:
package com.dswh.test;
import java.util.TimerTask;
public class Task1 extends TimerTask{
@Override
public void run() {
System.out.println("我是task1,每2s执行一次");
}
}
task2:
package com.dswh.test;
import java.util.TimerTask;
public class Task2 extends TimerTask {
@Override
public void run() {
System.out.println("我是task2,每3s执行一次");
}
}
测试:
package com.dswh.test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
private static Timer timer = new Timer();
public static void main(String[] args) throws Exception {
//新建task1
Task1 task1 = new Task1();
//新建task2
Task2 task2 = new Task2();
//调度
timer.schedule(task1, 0, 2000);
timer.schedule(task2, 0, 3000);
Thread.sleep(5000);
//取消定时任务
task1.cancel();
System.out.println("task1 cancel");
//此时就不能再调用task1了,否则会报Task already scheduled or cancelled
//想再次调用只能重新new Task1();
//新建task1
Task1 task1_1 = new Task1();
//再次调度
timer.schedule(task1_1, 0, 2000);
}
}
方式二:执行某些定时任务,我们可能需要传递些参数,这时我们可以使用下面这种方式
task1:
package com.dswh.test;
import java.util.TimerTask;
public class Task1{
public TimerTask getTask1(String s) {
return new TimerTask() {
@Override
public void run() {
System.out.println(s);
}
};
}
}
测试:
package com.dswh.test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
private static TimerTask task = null;
private static Timer timer = new Timer();
public static void main(String[] args) throws Exception {
//开始任务
startTask("我是传入的参数,执行task1任务");
Thread.sleep(3000);
//取消任务
endTask("任务结束了");
//再次开启
Thread.sleep(3000);
startTask("任务再次开启");
}
public static void startTask(String s) throws InterruptedException {
if (task==null) {
task = new Task1().getTask1(s);
}
timer.schedule(task, 0, 1000);
}
public static void endTask(String s) {
task.cancel();
task=null;
System.out.println(s);
}
}