`
scanfprintf123
  • 浏览: 79208 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多

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

 

比如,在读取网络请求的时候,我们希望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

 

 

看吧,两个简单的类,一个经典的设计模式,便很好的诠释了超时了该怎么办这个需求。如果你有这样的需求,不妨去试一试。

  • 大小: 5.8 KB
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics