最近在開發blog的註冊系統的時候遇到一個小小的困難,因爲blog的註冊是通過訪問blog系統的頁面並模擬人的行爲來爲用戶註冊的,在正常情況下是 沒有問題的,但是如果遇到異常,這樣的註冊方式就顯得很脆弱了,比如用戶已經註冊過,這個時候雖然頁面上會出現錯誤提示,但是用程序來捕捉這樣的提示比較 困難,而且如果這樣做還需要加上更多的判斷,考慮各種可能的異常情況,如果考慮不全,會極大降低該模塊的可靠度。考慮再三之後,索性我就不去考慮有哪些異 常情況了,全部統一處理,規定在一定時間內,這個註冊blog的行爲不能完成就認爲是註冊失敗。
處理方案是有了,那該怎麼實現這樣的功能呢?在網上查閱了許多資料之後,找到了有個叫做守護線程的東西,覺得用它來完成這樣的需求倒是挺方便的,所以在這裏分享給大家。
首先,守護線程類如下:
/**
* 本線程設置了一個超時時間
* 該線程開始運行後,經過指定超時時間,
* 該線程會拋出一個未檢查異常通知調用該線程的程序超時
* 在超時結束前可以調用該類的cancel方法取消計時
*/
public class TimeoutThread extends Thread{
/**
* 計時器超時時間
*/
private long timeout;
/**
* 計時是否被取消
*/
private boolean isCanceled = false;
/**
* 當計時器超時時拋出的異常
*/
private TimeoutException timeoutException;
/**
* 構造器
*
* @param timeout
* 指定超時的時間
*/
public TimeoutThread(long timeout, TimeoutException timeoutErr) {
super();
this.timeout = timeout;
this.timeoutException = timeoutErr;
// 設置本線程爲守護線程
this.setDaemon(true);
}
/**
* 取消計時
*/
public synchronized void cancel() {
isCanceled = true;
}
/**
* 啓動超時計時器
*/
public void run() {
try {
Thread.sleep(timeout);
if (!isCanceled)
throw timeoutException;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
下面定義要在TimeoutThread中拋出的異常,這個異常是關鍵,因爲我們完全依靠捕捉這個異常才能知道我們需要執行的任務是否超時了,而且 這個異常還有一個特殊之處在於,它不繼承自Exception,而是繼承自RuntimeException,這是爲什麼呢?原因是run方法重寫了 Thread中的run()方法,該方法不能拋出已檢測的異常:
public class TimeoutException extends RuntimeException {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 5961292480921511543L;
public TimeoutException(String errMessage){
super(errMessage);
}
}
現在萬事具備,工具已經做好了,就差在需要的地方使用了,這種方式使用起來也是特別簡潔明瞭,使用方法如下:
TimeoutThread t = new TimeoutThread(5000,new TimeoutException(”超時”));
try{
t.start();
//需要計時的任務
webAction();
t.cancel();
}catch(TimeoutException e){
//對超時的處理
throw new AreadyRegedException(”用戶可能已經註冊了blog,或訪問blog系統時發生異常,請檢查!”);
}