一個簡單的Java 計時器框架實現
本文介紹一個簡單的基于線程機制的計時器的實現。
將把 java.util.Timer 和 java.util.TimerTask 統稱為 Java 計時器框架,它們使程序員可以很容易地計劃簡單的任務。
計劃框架建立在 Java 定時器框架類的基礎之上。因此,在解釋如何使用計劃框架以及如何實現它之前,我們將首先看看如何用這些類進行計劃。
想象一個煮蛋計時器,在數分鐘之后(這時蛋煮好了)它會發出聲音提醒您。下例中的代碼構成了一個簡單的煮蛋計時器的基本結構:
EggTimer.java
import java.util.Timer;
import java.util.TimerTask;
public class EggTimer {
private final Timer timer = new Timer();
private final int minutes;
public EggTimer(int minutes) {
this.minutes = minutes;
}
public void start() {
timer.schedule(new TimerTask() {
public void run() {
playSound();
timer.cancel();
}
private void playSound() {
System.out.println("Your egg is ready!");
// Start a new thread to play a sound...
}
}, minutes * 60 * 1000);
}
public static void main(String[] args) {
EggTimer eggTimer = new EggTimer(2);
eggTimer.start();
}
}
|
EggTimer 實例擁有一個 Timer 實例,用于提供必要的計劃。用 start() 方法啟動煮蛋計時器后,它就計劃了一個 TimerTask ,在指定的分鐘數之后執行。時間到了, Timer 就在后臺調用 TimerTask 的 start() 方法,這會使它發出聲音。在取消計時器后這個應用程序就會中止。
java.util.Timer實現定時刪除信息線程
public class AlarmTimer {
static Logger log=Logger.getLogger(AlarmTimer.class);
private Timer timer = new Timer();
private int minutes;
private int type = VIRGIN;
private String id;
private Object o;
private static Map timerQuery;
public static final int VIRGIN = 0;
public static final int CALL_STATUS = 1;
public static final int CALL_SMS = 2;
public static final int CALL_MMS = 3;
public static final int UPDATE_LOCATION = 4;
public static final int DUR_LOCATION = 5;
static {
timerQuery = new ConcurrentHashMap();
}
public AlarmTimer() {}
public AlarmTimer(int minutes, int type, Object o, String id) {
this.minutes = minutes;
this.type = type;
this.o = o;
this.id = id;
}
@SuppressWarnings("unchecked")
public void start() {
timerQuery.put(id, timer);
timer.schedule(new TimerTask() {
public void run() {
if (type == 1) {
delStatus((ConcurrentHashMap) o, id);
timer.cancel();
} else if (type == 2) {
delSms((SmsBean) o, id);
timer.cancel();
} else if (type == 3) {
delMms((MmsBean) o, id);
timer.cancel();
} else if (type == 4) {
updateLocation((ConcurrentHashMap) o, id);
timer.cancel();
} else if (type == 5){
duraLocation ((ConcurrentHashMap) o, id);
timer.cancel();
}
}
private void delStatus(ConcurrentHashMap hMap, String RegId) {
hMap.remove(RegId);
log.info(RegId+ " status removed!");
}
private void delSms(SmsBean smsBean, String RegId) {
try {
Set keys = timerQuery.keySet();
Iterator e = keys.iterator();
while (e.hasNext()) {
String temp = (String) e.next();
if (temp.equals(RegId)) {
smsBean.deleteBysmsId(RegId);
timerQuery.remove(id);
log.info(RegId+ " sms removed!");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void delMms(MmsBean mmsBean, String RegId) {
try {
Set keys = timerQuery.keySet();
Iterator e = keys.iterator();
while (e.hasNext()) {
String temp = (String) e.next();
if (temp.equals(RegId)) {
mmsBean.deleteBymmsId(RegId);
timerQuery.remove(id);
log.info(RegId+ " mms removed!");
}
}
String TMP_PATH = Messages.getString("FILE_PATH");
String userName = mmsBean.getRegId();
String fileFullName = mmsBean.getFileUri();
String toDel = TMP_PATH + "/" + userName + "/"
+ fileFullName;
File file = new File(toDel);
if (file.delete()) {
log.info(RegId+ " mms file removed!");
} else {
log.warn(RegId+ " mms file does not exist!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void updateLocation(ConcurrentHashMap hMap, String RegId) {
Notification notiEvent = null;
if (hMap.containsKey(RegId)) {
notiEvent = (Notification) hMap.get(RegId);
String num = notiEvent.getAddress();
int frequency = notiEvent.getFrequency();
Location loc = new Location();
try {
double latitude = loc.queryLatitude(num);
double longitude = loc.queryLongtitude(num);
DateFormater dFormater = new DateFormater(new Date());
String timeStamp = dFormater.dateFormat();
notiEvent.setLatitude(latitude);
notiEvent.setLongitude(longitude);
notiEvent.setTimeStamp(timeStamp);
log.info(RegId+ " location update!");
AlarmTimer aTimer = new AlarmTimer(frequency,
AlarmTimer.UPDATE_LOCATION, hMap, RegId);
aTimer.start();
// ---just for test show---
log.info(RegId+ " latitude update:" + latitude + " at:"
+ timeStamp);
log.info(RegId+ " longitude update:" + longitude + " at:"
+ timeStamp);
// ------------------------
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void duraLocation(ConcurrentHashMap hMap,String RegId){
hMap.remove(RegId);
AlarmTimer aTimer=new AlarmTimer();
aTimer.delTimer(RegId);
LocationBean lBean=new LocationBean();
try {
lBean.delete(RegId);
} catch (Exception e) {
e.printStackTrace();
}
log.info(RegId+ " location service removed!");
}
}, minutes * 60 * 1000);
}
public void delTimer(String regId) {
this.id = regId;
Set keys = timerQuery.keySet();
Iterator e = keys.iterator();
while (e.hasNext()) {
String temp = (String) e.next();
if (temp.equals(id)) {
timer = (Timer) timerQuery.get(temp);
timerQuery.remove(id);
timer.cancel();
log.info(id+"Timer removed!");
}
}
}
}
|
1.構造子設計
public AlarmTimer(int minutes, int type, Object o, String id) {
this.minutes = minutes;
this.type = type;
this.o = o;
this.id = id;
}
|
由于傳入的數據結構類型不同,所以統一為Object類型,然后根據type類型定義,將其向下轉行為具體類型。
2.start()方法
start()方法體利用Timer類實現計時器線程。通過定義匿名內部類TimerTask來實現具體類型操作。cancel()起到銷毀線程的作用。
3.timerQuery設計
設計timerQuery目的是記錄所有啟動的新線程的句柄。這樣如果主動銷毀線程(而非在指定的時間,即比指定時間早的情況下),可以檢查此表,獲得對象句柄(參見delTimer方法)。
4.匿名類TimerTask類中方法分析
delStatus/delSms/delMms功能類似,即從相應的數據存儲體中刪除數據,并在timerQuery中刪除該線程的句柄。
updateLocation方法的目的是每隔一段時間來更新數據存儲體中的數據。具體實現方法是在指定時間得到線程讀出它的id,并更新它的數據。啟動一個新的線程將數據保存在新線程中,原線程銷毀。如此往復,直到在Map中找不到此id的線程。
duraLocation方法的目的是在指定的時間銷毀Map中的線程。