我們在開發的時候,常常會有這樣的需要,需要保證某個操作只運行一段時間,如果超時了,就執行對應的超時操作。
?
比如,在讀取網絡請求的時候,我們希望3秒內能讀到數據,如果超過了3秒沒有讀到,那么就不讀了,提示用戶,超時了,需要重試。
比如,我們開啟了一個進程來執行一條命令,這個命令可能是批量處理一批文件并生成一個報告,或者其它,我們知道這個命令肯定不會執行超過30分鐘,那么,我們需要給它設定一個時間,如果超時了,那么我們就殺掉該進程, 并清除掉錯誤的生成數據。
比如,我們通過USB接口將設備如電紙書,MP4等連接到電腦,如果嘗試連接了一段時間而沒有連接上,那么會給出指導,讓用戶檢查設備或者進行重試。
?
諸如此類,還有很多。
?
對于第一種情況,我們還有選擇,例如,我們可以通過設置socket的timeout時間來達到這個目的,但是對于大多數情況,它們都沒有給我們太多這樣原生的方式進行選擇。
?
但是,對于這樣的需求,apache-common-exec包中的WatchDog還是給了我們一個很好的例子。
?
?
?
這是一個簡單的監聽者模式的實現,WatchDog是Subject,TimeoutObserver自然就是Observer,從上圖可以看出,WatchDog有著經典Subject的3個職責:
1. 管理Observer的職責,如addTimeoutObserver(),removeTimeoutObserver()方法
2. 觸發Observer的職責,如fireTimeoutOccured()
3. 自己本身的業務邏輯,在run()方法中。
?
從類圖上看,可以看出WatchDog類實現了Runnable接口,它在運行時實際上是一個deamon線程,看它的start()方法的實現:
?
?
public synchronized void start() { stopped = false; Thread t = new Thread(this, "WATCHDOG"); t.setDaemon(true); t.start(); }
而它自己本身的業務邏輯則很簡單,就是判斷什么時候超時然后觸發TimeoutObserver的timeoutOccured(w : Watchdog) : void 方法:
?
?
public synchronized void run() { final long until = System.currentTimeMillis() + timeout; long now; while (!stopped && until > (now = System.currentTimeMillis())) { try { wait(until - now); } catch (InterruptedException e) { } } if (!stopped) { fireTimeoutOccured(); //trigger TimeoutObserver#timeoutOccred() operation } } protected final void fireTimeoutOccured() { Enumeration e = observers.elements(); while (e.hasMoreElements()) { ((TimeoutObserver) e.nextElement()).timeoutOccured(this); } }?
?
代碼很簡單,是不是?當我們有超時了需要進行某種操作的需求時,只需要將你需要進行的操作放到實現了TimeoutObserver接口的類中,比如:
?
?
public class NotifyUserTimeout implements TimeoutObserver { @Override public void timeoutOccured(Watchdog w) { System.out.println("Timeout happens.. exit the applicaton now"); System.exit(-1); } }?
然后調用WatchDog類進行超時時間的設置以及注冊實現的TimeoutObserver即可。
?
?
static main(args) { Watchdog watchDog=new Watchdog(3000);//set timeout for 3 seconds watchDog.addTimeoutObserver new NotifyUserTimeout() watchDog.start(); //simulate time-consuming task.. Thread.sleep 5000 println "finish normally.." }
?
?
從上可以看到,我們模擬了正常的操作大概需要5秒,但是設置了超時的時限為3秒,當正常的操作超時后,會進行提示用戶并且退出,上面的例子的結果輸出為:
?
Timeout happens.. exit the applicaton now
?
?
看吧,兩個簡單的類,一個經典的設計模式,便很好的詮釋了超時了該怎么辦這個需求。如果你有這樣的需求,不妨去試一試。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
