清单 10. 稍后执行
import java.util.*;
public class Later
{
public static void main(String[] args)
{
Timer t = new Timer("TimerThread");
t.schedule(new TimerTask() {
public void run() {
System.out.println("This is later");
System.exit(0);
}
}, 1 * 1000);
System.out.println("Exiting main()");
}
}
public class Later
{
public static void main(String[] args)
{
Timer t = new Timer("TimerThread");
t.schedule(new TimerTask() {
public void run() {
System.out.println("This is later");
System.exit(0);
}
}, 1 * 1000);
System.out.println("Exiting main()");
}
}
Timer 有许多 schedule() 重载,它们提示某一任务是一次性还是重复的,并且有一个启动的 TimerTask 实例。TimerTask 实际上是一个 Runnable(事实上,它实现了它),但还有另外两个方法:cancel() 用来取消任务,scheduledExecutionTime() 用来返回任务何时启动的近似值。
请注意 Timer 却创建了一个非守护线程在后台启动任务,因此在清单 10 中我需要调用 System.exit() 来取消任务。在长时间运行的程序中,最好创建一个 Timer 守护线程(使用带有指示守护线程状态的参数的构造函数),从而它不会让 VM 活动。
这个类没什么神奇的,但它确实能帮助我们对后台启动的程序的目的了解得更清楚。它还能节省一些 Thread 代码,并作为轻量级 ScheduledExecutorService(对于还没准备好了解整个 java.util.concurrent 包的人来说)。
5. JavaSound
尽管在服务器端应用程序中不常出现,但 sound 对管理员有着有用的 “被动” 意义 — 它是恶作剧的好材料。尽管它很晚才出现在 Java 平台中,JavaSound API 最终还是加入了核心运行时库,封装在 javax.sound * 包 — 其中一个包是 MIDI 文件,另一个是音频文件示例(如普遍的 .WAV 文件格式)。
JavaSound 的 “hello world” 是播放一个片段,如清单 11 所示:
清单 11. 再放一遍,Sam
public static void playClip(String audioFile)
{
try
{
AudioInputStream inputStream =
AudioSystem.getAudioInputStream(
this.getClass().getResourceAsStream(audioFile));
DataLine.Info info =
new DataLine.Info( Clip.class, audioInputStream.getFormat() );
Clip clip = (Clip) AudioSystem.getLine(info);
clip.addLineListener(new LineListener() {
public void update(LineEvent e) {
if (e.getType() == LineEvent.Type.STOP) {
synchronized(clip) {
clip.notify();
}
}
}
});
clip.open(audioInputStream);
clip.setFramePosition(0);
clip.start();
synchronized (clip) {
clip.wait();
}
clip.drain();
clip.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
{
try
{
AudioInputStream inputStream =
AudioSystem.getAudioInputStream(
this.getClass().getResourceAsStream(audioFile));
DataLine.Info info =
new DataLine.Info( Clip.class, audioInputStream.getFormat() );
Clip clip = (Clip) AudioSystem.getLine(info);
clip.addLineListener(new LineListener() {
public void update(LineEvent e) {
if (e.getType() == LineEvent.Type.STOP) {
synchronized(clip) {
clip.notify();
}
}
}
});
clip.open(audioInputStream);
clip.setFramePosition(0);
clip.start();
synchronized (clip) {
clip.wait();
}
clip.drain();
clip.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}