代码之美一---超时了怎么办?

系统 1227 0

我们在开发的时候,常常会有这样的需要,需要保证某个操作只运行一段时间,如果超时了,就执行对应的超时操作。

 

比如,在读取网络请求的时候,我们希望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元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论