一.何時需要超時控制
超時控制一般使用阻塞時間比較長的操作上,有可能是和遠程數據庫的連接, 也有可能是網絡下載,在程序超時後, 往往需要進行一些操作,比如退出線程,或 者重新執行.
二.實現方法
方法1.(原創)
實現描述:使用一個守護線程作為計時器,並且在計時結束時拋出一個未檢測 異常。
具體實現:
類1:守護線程類
/**
* 本線程設置了一個超時時間
* 該線程開始運行後,經 過指定超時時間,
* 該線程會拋出一個未檢查異常通知調用該線程的程序 超時
* 在超時結束前可以調用該類的cancel方法取消計時
* @author solonote
*/
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();
}
}
}
注: 類一中的TimeoutException是下邊的用戶自定義類,不是java中的 java.util.concurrent.TimeoutException
類2.拋出異常類,該類繼承了RuntimeException,原因是run方法不能拋出已 檢測異常。
public class TimeoutException extends RuntimeException {
/**
* 序列化號
*/
private static final long serialVersionUID = -8078853655388692688L;
public TimeoutException(String errMessage)
{
super(errMessage);
}
}
使用方法:
//初始化超時類
TimeoutThread t = new TimeoutThread(5000,new TimeoutException("超時"));
try{
t.start ();
.....要檢測超時的程序段....
t.cancel();
}catch (TimeoutException e)
{
...對超時的處理...
}
TimeoutException可以更換為其他未檢查異常類。
方法說明:
本方法的使用可以實現線程自己管理超時,並且可以管理某一段代碼超時時, 可以在方法內部給出處理辦法。
但是需要注意的是:本方法的超時時間並不是當前線程的運行時間,而是計時 器開始計時起系統運行的時間。
方法2:
是用join方法,在外部管理線程超時。Thread對象有一個join(long millis) 方法,執行該方法時如果另一個線程中斷了當前線程,就會拋出一個 InterruptedException異常。可以采用這個機制在一個線 程的外部處理這個線 程的異常。我覺得這個方法很有局限性,因為是在外部定義該線程的方法,就只 能對整個線程的run方法做出線程超時控制,而並不是對 run方法中的某一段代 碼。並且該方法處理線程超時的處理方法也只能寫在線程的外部。不過這個方法 的超時定義是當前線程的運行時間。
至於采用何種方法,根據個人的應用而定吧。