在应用开发中,经常需要一些周期性的操作,比如每5分钟检查一下新邮件等。对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。比如下面的代码每5分钟检查一遍是否有新邮件:
-
private
java.util.Timer
timer;
-
timer = new
Timer
(true
);
-
timer.schedule(new
java.util.TimerTask
() {
-
public
void
run() {
-
//server.checkNewMail(); 检查新邮件
-
}
-
}, 0, 5*60*1000);
使用这几行代码之后,Timer本身会每隔5分钟调用一遍server.checkNewMail()方法,不需要自己启动线程。Timer本身也是多线程同步的,多个线程可以共用一个Timer,不需要外部的同步代码。
在《The Java Tutorial》中有更完整的例子:
-
public
class
AnnoyingBeep {
-
Toolkit
toolkit;
-
Timer
timer;
-
-
public
AnnoyingBeep() {
-
toolkit = Toolkit
.getDefaultToolkit();
-
timer = new
Timer
();
-
timer.schedule(new
RemindTask(),
-
0, //initial delay
-
1*1000); //subsequent rate
-
}
-
-
class
RemindTask extends
TimerTask
{
-
int
numWarningBeeps = 3;
-
-
public
void
run() {
-
if
(numWarningBeeps > 0) {
-
toolkit.beep();
-
System
.out.println("Beep!"
);
-
numWarningBeeps--;
-
} else
{
-
toolkit.beep();
-
System
.out.println("Time's up!"
);
-
//timer.cancel(); //Not necessary because we call System.exit
-
System
.exit(0); //Stops the AWT thread (and everything else)
-
}
-
}
-
}
-
...
-
}
这段程序,每隔3秒响铃一声,并打印出一行消息。循环3次。程序输出如下:
Task scheduled.
Beep!
Beep! //one second after the first beep
Beep! //one second after the second beep
Time's up! //one second after the third beep
Timer类也可以方便地用来作为延迟执行,比如下面的代码延迟指定的时间(以秒为单位)执行某操作。类似电视的延迟关机功能。
-
...
-
public
class
ReminderBeep {
-
...
-
public
ReminderBeep(int
seconds) {
-
toolkit = Toolkit
.getDefaultToolkit();
-
timer = new
Timer
();
-
timer.schedule(new
RemindTask(), seconds*1000);
-
}
-
-
class
RemindTask extends
TimerTask
{
-
public
void
run() {
-
System
.out.println("Time's up!"
);
-
toolkit.beep();
-
//timer.cancel(); //Not necessary because we call System.exit
-
System
.exit(0); //Stops the AWT thread (and everything else)
-
}
-
}
-
...
-
}
===========================================================
一些注意的问题:
1. 如果希望自己的Task一直运行,而不是像上面的RemindTask那样仅循环3次。
这
很简单,Task仅代表了一次的动作。而不是让Task完成循环。上面的RemindTask中之所以有一个计数,是因为要运行3次停止,如果需要一直保
持运行。把上面有关的计数的代码全部去除即可。其实Timer中并没有提供运行指定次数后即停止的机制,所以,上面的计数满足了这个功能需要。
2. 能否设置Timer的优先级?
Timer
中是利用一个线程来进行计时及周期触发动作的。现在的Timer实现中并没有提供设置优先级的方法,在你调用new Timer()时线程已经启动,所
以,除非Timer的以后版本中在构造方法中增加优先级参数,否则,我们是不能控制其优先级的。现在的Timer默认是在
Thread.NORM_PRIORITY优先级下运行的。但是Timer提供了一个Timer(boolean isDaemon)的构造方法,可以将
Timer设置为daemon线程。这样,在你的程序中其它线程都运行完毕后,程序就可以退出了。
3. Timer是不是实现了精确地定时?
否。Timer中也是采用Object.wait(long time)来实现定时的,由于Object.wait()不保证精确计时,所以Timer也不是一个精确的时钟。如果是实时系统,不能依赖Timer。
4. 假如在一个Timer类里面再定义一个Timer类,外层定义的时间是24小时循环一次,而内层定义的是1小时循环一次,意思就是当一个小时内层运行完一次之后,内层Timer释放资源,那么外层的Timer是不是也会释放,还是24小时之中一直都在占用?
不
太清楚此占用资源是什么意思,如果在Task中用到一些资源,这些资源应该在Task运行结束后即刻释放,尤其对竞态条件,更应该占用尽量少的时间。一般
来说,一次Task的运行时间,将少于你设定的周期。否则,Task将在Timer中堆积起来。如果要实现上面说的每24小时和每1小时两个周期的操作,
可以使用一个Timer,schedule两个Task即可。
5. Timer是否可以在多线程环境下使用?
可以。Timer中用于存储Task的容器是同步了的,保证了多线程环境先的安全使用。
6. 定时的时间能为变量,可以在程序中变化吗?就是说定时的时间可以又界面来控制。
一
个Timer可以控制任意多个Task的不同周期设定的触发。也就是说,这个Timer类似于可以定多个时间的闹钟,比如我的手机就有3个闹
钟 :) 。但是一旦一个Task 已经进行了schedule了,那么就不能再次进行设定。所以,也不可能再改变其周期、延迟等等设定了。可以看下面
的代码:
-
synchronized
(task.lock) {
-
if
(task.state != TimerTask
.VIRGIN)
-
throw
new
IllegalStateException
(
-
"Task already scheduled or cancelled"
);
-
task.nextExecutionTime = time;
-
task.period = period;
-
task.state = TimerTask
.SCHEDULED;
-
}
7. 可不可以认为Timer就是一个线程的发射器?
Timer中仅有一个存储Task的Queue和一个调度所有Task的线程。不管你schedule几次,在Timer上加了几个Task,都只有一个后台的线程进行调度。
分享到:
相关推荐
Java.util.ConcurrentModificationException 异常问题详解 ConcurrentModificationException 异常是 Java 中一个常见的异常,它发生在 Iterator 遍历集合时,集合同时被修改引起的异常。在 Java 中,集合类如 ...
Java.util包是Java标准库中的核心包之一,它包含了大量用于日常编程的工具类和接口。这个包在Java 2版本中得到了显著增强,引入了许多重要的数据结构和算法,为Java程序员提供了更丰富的功能。 首先,Java.util包中...
java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,...
java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,即...
定时调度可以使用java.util.Timer和java.util.TimerTask,或使用更现代的java.concurrent包中的ScheduledExecutorService。 以上就是Java常用类库的一些核心知识点,涵盖了字符串处理、系统交互、国际化、日期时间...
java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,...
java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,即...
java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,即...
闹钟功能通常涉及到定时任务,Java的`java.util.Timer`和`java.util.TimerTask`类可以实现这一功能。你可以创建一个`TimerTask`子类,定义具体的任务行为,然后使用`Timer`来安排任务的执行。例如,设定在特定时间...
java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,...
java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,...
java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,即...
这通常通过实现`java.lang.Runnable`接口并创建`Thread`对象,或者使用`javax.swing.Timer`来实现。后者更适合于GUI应用,因为它能更好地与Swing事件调度线程同步,避免界面更新时出现的闪烁问题。 5. **GUI布局...
9. **文件操作**:对于涉及文件修改的定时任务,需要掌握Java的I/O流和NIO API来读取、写入或删除文件。 10. **并发编程**:在处理多任务同时执行时,需要了解并发编程的概念,如锁、同步、并发容器等,以避免竞态...
2. **定时机制**:在Java中,可以使用`java.util.Timer`和`java.util.TimerTask`类来创建定时任务。jAlarm很可能就是通过这些类来设定提醒时间,并在到达指定时间时触发提醒事件。此外,Java 8引入了`java.time`包,...
首先,我们需要了解Java中的定时器类`java.util.Timer`和`java.util.TimerTask`。`Timer`类是线程安全的,它允许我们调度一次性或重复性的任务。`TimerTask`是实际执行的任务,它继承自`Runnable`接口,但提供了更...
这可能涉及到线程管理和定时任务,如`java.util.Timer`或`java.util.concurrent.ScheduledExecutorService`。 4. **用户界面**:为了提供友好的交互体验,开发者可能使用了Java Swing或JavaFX创建窗口、按钮、...