Timer与TimerTask
联网和拍照这两种情况都需要程序员创建新的线程来完成任务并且这种做法对于程序员来说是显式的即通过直接使用Thread类或Runnable接口来直接创建新线程在MIDP的API中同样提供了隐式的方式来创建新线程以方便程序员的编程这就是TimerTask类它实现了Runnable接口用户只需创建一个继承它的类并且实现run()方法以此来创建新线程而无需显示的继承Thread或Runnable
当然TimerTask的优点不仅于此从它的名字来看可以认为它是一个在特定时间执行的任务run()方法中代码就是这任务那么怎么控制其在特定时间执行呢?这就需要Timer这个类的帮助了顾名思义Timer是一个定时器通过调用它的多个schedule()方法中的一个可以控制在特定的时间或每隔一定时间执行TimerTask具体的方法介绍请看JDK文档
TimerTask和Timer经常一起使用比如在显示时间倒计时和显示欢迎界面时会经常用到下面就通过一个实例来介绍这两个的用法
这是一个计时的程序程序从秒开始用户可以随时暂停或继续计时程序是通过Timer和TimerTask来完成的包含三个类ClockMidletClockCanvas和Clock首先来看一下本程序最主要的类ClockCanvas
以下是引用片段
/**
*ClockCanvasjava
*/
packagenjuhysteriathreadclock;
importjavautilTimer;
importjavaxmicroeditionlcduiCanvas;
importjavaxmicroeditionlcduiCommand;
importjavaxmicroeditionlcduiCommandListener;
importjavaxmicroeditionlcduiDisplayable;
importjavaxmicroeditionlcduiFont;
importjavaxmicroeditionlcduiGraphics;
/**
*Thisclassdisplaytimetouserandalsostartthetimer
*toupdatetimeeachsecond
*@authorMagic
*
*/
publicclassClockCanvasextendsCanvasimplementsCommandListener{
privateClockMidletmidlet;
privateCommandexitCommand;
privateCommandstopCommand;
privateCommandresumeCommand;
privatelongsecond;
privateintx;
privateinty;
//Timer privateTimertimer;
publicClockCanvas(ClockMidletmidlet){
thismidlet=midlet;
exitCommand=newCommand(退出CommandEXIT);
stopCommand=newCommand(停止CommandSCREEN);
resumeCommand=newCommand(继续CommandSCREEN);
addCommand(exitCommand);
addCommand(stopCommand);
setCommandListener(this);
second=;
x=getWidth()/;
y=getHeight()/;
//Createtimerandstartit timer=newTimer();
timerschedule(newClock(this));
}
/**
*Addonesecond
*
*/
publicvoidaddSecond(){
second++;
}
protectedvoidpaint(Graphicsg){
gsetColor();
gfillRect(getWidth()getHeight());
gsetColor();
gsetFont(FontgetFont(FontFACE_SYSTEMFontSTYLE_PLAINFontSIZE_LARGE));
//Drawsecond gdrawString(StringvalueOf(second)xyGraphicsLEFT|GraphicsTOP);
}
publicvoidcommandAction(CommandcmdDisplayabledisplayable){
if(cmd==exitCommand){
timercancel();
midletdestroyApp(false);
midletnotifyDestroyed();
}elseif(cmd==stopCommand){
timercancel(); removeCommand(stopCommand);
addCommand(resumeCommand);
}elseif(cmd==resumeCommand){
timer=null; timer=newTimer();
timerschedule(newClock(this));
removeCommand(resumeCommand);
addCommand(stopCommand);
}
}
} ClockCanvas继承了Canvas用来向用户显示当前的秒数注意构造函数中黑体的代码创建了Timer并且调用schedule()方法来设定运行任务的时间第一个参数是TimerTask的对象这里是Clock它继承了TimerTask我们将稍后讨论第二个参数是运行的延迟这里为也就是立刻执行第三个参数是连续运行的时间间隔这里为毫秒也就是每隔秒钟更新界面
注意commandAction()方法在处理停止命令时需要停止计时此处调用timercancle()来取消计时器所以界面将停止更新当按下继续命令后又需要继续开始计时所以我们重新创建了Timer因为原来的已经取消了是不可用的了
接着就来看看Clock是如何来工作的代码如下
以下是引用片段
/**
*Clockjava
*/
packagenjuhysteriathreadclock;
importjavautilTimerTask;
/**
*Updatethetime
*@authorMagic
*
*/
publicclassClockextendsTimerTask{
privateClockCanvascanvas;
publicClock(ClockCanvascanvas){
thiscanvas=canvas;
}
publicvoidrun(){
canvasaddSecond();
canvasrepaint();
}
}
非常简单在run()方法中就是调用了ClockCanvas类中addSencond()方法来增加时间同时调用repaint()来更新界面从表面上看几乎没有多线程的痕迹其实创建Timer的时候就相当于在后台创建了一个新的线程它控制着TimerTask的执行因此对于秒数的增加是在另一个线程的完成的而主线程只负责更新显示
在加上下面的ClockMidlet就可以运行程序了
以下是引用片段
/**
*ClockMidletjava
*/
packagenjuhysteriathreadclock;
importjavaxmicroeditionlcduiCanvas;
importjavaxmicroeditionlcduiDisplay;
importjavaxmicroeditionmidletMIDlet;
/**
*ClockMIDlet
*@authorMagic
*
*/
publicclassClockMidletextendsMIDlet{
privateDisplaydisplay;
privateCanvasclockCanvas;
publicClockMidlet(){
super();
display=DisplaygetDisplay(this);
}
protectedvoidstartApp(){
clockCanvas=newClockCanvas(this);
displaysetCurrent(clockCanvas);
}
protectedvoidpauseApp(){
}
protectedvoiddestroyApp(booleanarg){
}
} 运行程序将以秒为单位进行计时如图所示
图
总 结
以上介绍了多线程技术在联网拍照中的应用以及MIDP自带的TimerTask和Timer的使用方法在实际编程过程中会遇到更多的使用多线程的情况比如播放背景音乐等但基本方法都是如此这里不再赘述了
由于笔者水平有限以上论述只是蜻蜓点水未能深入讨论多线程的使用特别是防止死锁以及wait()/notify()的使用