您的位置:首页 > 编程语言 > Java开发

java中定时器timer类的实现和源代码

2007-08-13 14:04 639 查看
在Windows 编程中可以调用SetTimer在指定窗口安装定时器(Timer),定时器可以在指定的时间间隔周期性回调用户指定的方法,用来执行周期性的任务,如果 想取消定时器,可以调用KillTimer取消。但是在java标准包里中并没有这种类。下面介绍的这个类包可以实现上述功能。

下面是接口,需要支持定时器功能的类要实现这个接口:

TimerClient.java

package com.ly.util;

/**
* TimerClient Interface
*
* @version 1.0, 8 October 1995
*
*/
public interface TimerClient
{
void timerEvent(int id);
}

下 面是定时器的实现,包括三个类:TimerCtl,TimerTask,TimerTasks。其中TimerTask用来描述定时器信息。 TimerTasks是一个TimerTask的列表,这样我们就可以同时在一个应用中安插多个定时器。TimerCtl是定时器控制类,是个线程,不停 地检查TimerTasks中是否有TimerTask到期,要是有TimerTask到达指定的时间,则回调TimerTask指定的 TimerClient的timerEvent接口。

TimerCtl.java

package com.ly.util;

import java.util.Vector;
import java.util.Enumeration;
//import com.borland.jb.util.Diagnostic;

/**
* Timer Component
*
* Note:
* - The successful operation of this timer requires clients to execute simple, short
* code snippets when called back by the engine. Otherwise the queue's delivery
* mechanism will be held up
*
* Further work:
* - When Thread.Interrupt is implemented we can switch from the busy wait model to
* the calculated wait model. Without the interrupt the thread waits for the
* calculated interval before waking up. This is a problem if another shorter
* request arrives. For now we'll assume the minimum resolution of the timer is
* 100ms.
*
* @version 1.0, 2 October 1995
*
*/
public class TimerCtl
{
static TimerTasks timerTasks;

public TimerCtl() {
}

/*
* Start a timer running
*/
public static void startTimer(TimerClient client, int eventId, long delay, boolean repeat) {
// create the timer if necessary
if (timerTasks == null) {
timerTasks = new TimerTasks();
timerTasks.start();
}

//Diagnostic.out.println("TIMER: startTimer"+eventId);

// add the new task to the queue
timerTasks.add(client, eventId, delay, repeat);
}

/*
* Stop a timer
*/
public static void stopTimer(TimerClient client, int eventId) {
//Diagnostic.out.println("TIMER: stopTimer"+eventId);
if(timerTasks != null)
timerTasks.end(client, eventId);
}
}

class TimerTasks extends Thread
{
Vector tasks = new Vector();
boolean suspended = false;
boolean sleeping = false;

/**
* Thread task runner
*/
public void run() {
// Loop forever
while (true) {
long sleepTime = 0;

// Ensure that the tasks class is protected
synchronized (tasks) {
//Diagnostic.out.println("TIMER: Tick");

// Scan the job list for any jobs which may fire.
// Mark one-shot jobs for deletion
// Calculate the maximum time we can sleep for
sleepTime = scan();

// Delete DeletePending jobs. DeletePending jobs result from one-shots which have
// been sent, and repeat jobs which have been cancelled. Jobs may have been
// cancelled during the Scan process.
purge();
}

// Suspend timer if necessary
if (tasks.size() == 0) {
//Diagnostic.out.println("TIMER: Suspend");
try {
synchronized(this) {
suspended = true;
wait();
}
}
catch (InterruptedException e) {
}
}
else {
//Diagnostic.out.println("TIMER: Suggested Sleeping for "+sleepTime);
if (sleepTime >= 0) {
try {
sleeping = true;
sleep(sleepTime);
sleepTime=scan();
sleeping = false;
}
catch (InterruptedException i) {
//Diagnostic.out.println("TIMER: Caught me napping");
}
}
}
}
}

/**
* Add a new task
*/
public void add(TimerClient client, int eventId, long delay, boolean repeat) {
TimerTask t = new TimerTask(client, eventId, delay, repeat);

synchronized (tasks) {
tasks.addElement((Object)t);
}

// Want instant response - wake the thread if it's napping
// unfortunately the interrupt() method is not working
// if (sleeping)
// interrupt();

if (suspended) {
synchronized(this) {
notify();
//Diagnostic.out.println("TIMER: Resume");
suspended = false;
}
}
}

/**
* Find the job and mark it for deletion
*/
public void end(TimerClient client, int eventId) {
synchronized (tasks) {
for (int i = 0; i < tasks.size(); i++) {
TimerTask t = (TimerTask)tasks.elementAt(i);

//if (!t.deletePending && t.client == client && t.eventId == eventId)
if (t.deletePending == false && t.client == client && t.eventId == eventId) {
// JPBS - if we don't reset 'repeat', deletePending will be set again
t.repeat = false;
t.deletePending = true;
break;
}
}
}
}

/**
* Clear out all the dead wood
*/
void purge() {
for (int i = 0; i < tasks.size(); i++) {
TimerTask t = (TimerTask)tasks.elementAt(i);

if (t.deletePending) {
//Diagnostic.out.println("TIMER: purged");

tasks.removeElementAt(i);
i--;
}
}
}

long scan() {
// The value added to the current time determines the MAX time until
// the next scan
// This is 100 now since thread.interrupt() is not implemented
long nextTime = System.currentTimeMillis() + 100;

for (int i = 0; i < tasks.size(); i++) {
TimerTask t = (TimerTask)tasks.elementAt(i);

// if not already deletePending, test (and possibly send the event)
// as a result, the job may be flagged for deletion.
// May also be a non-repeating job and so require self deletion
if (!t.deletePending)
t.test();

// if the task didn't get deleted - see what it contributes to the time
if (!t.deletePending)
nextTime = Math.min(nextTime, t.timeNext);

//Diagnostic.out.println("TIMER: Scanning "+t.eventId+" "+(t.deletePending == true ? "DEL" : ""));
}

return nextTime - System.currentTimeMillis();
}
}

class TimerTask
{
TimerClient client;
int eventId;

long timePrev;
long timeDelay;
long timeNext;

boolean repeat;
boolean deletePending;

public TimerTask(TimerClient client, int eventId, long timeDelay, boolean repeat) {
this.client = client;
this.eventId = eventId;
this.timeDelay = timeDelay;
this.repeat = repeat;

// schedule the next click - now + delay
timeNext = System.currentTimeMillis() + timeDelay;
deletePending = false;

//Diagnostic.out.println("TIMER: Adding New Task");
}

public void test() {
if (System.currentTimeMillis() >= timeNext) {
//Diagnostic.out.println("TIMER: fire");

// Fire the event
client.timerEvent(eventId);

// Update the next time
timeNext = System.currentTimeMillis() + timeDelay;

deletePending = !repeat;
}
}
}

 
下面是一个使用例子

TimerTest.java

package com.ly.util;

import java.io.*;
import java.util.*;
import com.ly.util.*;

/**
* Title:
* Description:
* Copyright: Copyright (c) 2001
* Company: http://dozb.blogchina.com
* @author dozb
* @version 1.0
*/
public class TimerTest implements TimerClient{
public TimerTest()
{
starttime();
}
public void timerEvent(int id)
{
System.out.println("timerEvent...");
}
public void starttime()
{
TimerCtl.startTimer(this,1,5*1000,true);
}
public void stoptime()
{
TimerCtl.stopTimer(this,1);
}

public static void main(String[] args)
{
new TimerTest();
try
{
Thread.sleep(200000);
}catch(Exception e)
{
}

}
}

通过这种方式,可以高效地使用socket通讯,在异步socket版本没有发布以前,不失是一种解决问题的方法。:)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: