使用过javascript的都知道有两个关于定时的方法:setTimeOut和setInterval方法,可以让一段代码持续性或者规定时间后运行。这样就可以实现定时的功能,最经典的应用就是贪吃蛇那条蛇持续性的走动。这里做一下关于定时器使用的一点小结
定时器:Timer
定时器的任务:TimerTask
定时器:Timer
一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
有关于定时器定时、任务调度、任务终止等多个api。详细参考java的开发文档
定时器的任务:TimerTask
由TimerTask 的定义知:
public abstract class TimerTask extends Object implements Runnable
它是一个线程。
由构造方法知:创建的是一个定时器任务,相对应于Timer调度的单元
案例1:实现隔一段时间后运行一段代码:类似js的setTimeOut函数
以下代码可以贴到main方法中运行
/**
* 1s后boom!相对于js的setTimeOut函数
*/
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println("boom!");
}
}, 1000);
案例2:实现每隔一段时间执行一段代码:类似js的setInterval函数
/**
* 通过方法内部类实现持续性间隔一段时间boom!
*/
class MyTimerTask extends TimerTask{
@Override
public void run() {
System.out.println("booming!");
new Timer().schedule(this, 1000);
}
}
//执行间断性运行
new Timer().schedule(new MyTimerTask(), 1000);
运行结果:
booming!
Exception in thread "Timer-1" java.lang.IllegalStateException: Task already scheduled or cancelled
at java.util.Timer.sched(Timer.java:358)
at java.util.Timer.schedule(Timer.java:170)
at cn.mym.timer.TimerTest$1MyTimerTask.run(TimerTest.java:29)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
报错原因:因为定时器的任务已经被使用了一次,所以TimerTask线程已经被调度了就不能被再次使用。就像炸弹一样,爆炸了就不能再爆一次。那么要实现这种功能需要做些改进:即定时器下一次执行的不是this这个自己本身TimerTask,而是一个新的TimerTask:
/**
* 通过方法内部类实现持续性间隔一段时间boom!
*/
class MyTimerTask extends TimerTask{
@Override
public void run() {
System.out.println("booming!");
new Timer().schedule(new MyTimerTask(), 1000);
}
}
//执行间断性运行
new Timer().schedule(new MyTimerTask(), 1000);
即:下一次执行的定时器任务TimerTask是一个新的定时器任务,这样就实现了循环间断
运行如下:
booming!
booming!
booming!
booming!
。。。
3.实现间断不同的时间:1000,2000,交替间断
以上及以下的方法都在main方法中:
本例完整:
public class TimerTest {
static int count = 1;
public static void main(String[] args) {
/**
* 通过方法内部类实现持续性间隔一段时间boom!
*/
class MyTimerTask extends TimerTask{
@Override
/**
* 实现间断不同的时间:1000,2000,交替间断
* 思路:通过一个全局属性来决定本次间断时间1000,还是2000
*/
public void run() {
System.out.println("booming!");
new Timer().schedule(new MyTimerTask(), 1000+1000*count);
count = (++count)%2;//每次的值是1或0
}
}
new Timer().schedule(new MyTimerTask(), 1000);
}
}
运行效果达到!
案例小结
那么以上的几种实现:Timer类有相关的调度api,可以翻阅:
void schedule(TimerTask task, Date time)
安排在指定的时间执行指定的任务。
void schedule(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定延迟执行。
void schedule(TimerTask task, long delay)
安排在指定延迟后执行指定的任务。
void schedule(TimerTask task, long delay, long period)
安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
最后小结
实际工作中可能存在的需求如:每周1-5的晚上10点收邮件,周六日上午10点收邮件,那么就需要用到定时器,如果用Timer和TimerTask就比较麻烦。 实际上有一个开源的项目:quartz 提供了关于时间调度的很不错的API
以上为多线程的一点个人总结,后期继续跟上。若有表述不当之处,感谢您的私信指出,我将尽快解决