有时候碰到一种情况,远程请求一个任务,但是请求时间不能超过一定时间,超过后按超时处理,这种情况我们可以用一段代码来实现,但是如果我们实现成一个类 ,则可以让代码更简洁,更具有健壮性
首先定义一个接口
public interface TimeOut<T> extends Callable<T> {
void onTimeout();
void start();
}
start方法表示开始这个任务,onTimeout方法超时后的动作,该接口继承了Callable,也就是这个接口是可以线程执行的
接着我们定义一个抽象类来简单封装一下:
public abstract class AbstractTimeOutTask<T> implements TimeOut<T> {
private volatile boolean done = false ;
@Override
public void onTimeout() {
System.out.println("this task is time out.");
}
@Override
public void start() {
Future<T> result = executor.submit(this);
try {
T res = result.get(timeout(),TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
if(result.isDone()||done) {
onTimeout();
}
}
}
protected void done(){
this.done = true ;
}
protected abstract long timeout();
ThreadPoolExecutor executor = new ThreadPoolExecutor(2,2,5, TimeUnit.MINUTES,new LinkedBlockingQueue<>());
}
这里定义了一个线程池,当然这个也可以通过方法来获取,最好是定义一个static的,不然每次创建对象都会创建一个线程池
这样就成了一个简单的封装,我们可以结合上次的消息通知来测试一下:
实现一个Timeout任务,并实现接口EventHandler
public class OrangeTimeOutTask extends AbstractTimeOutTask<String> implements EventHandler<TestEvent> {
@Override
protected long timeout() {
return 3000;
}
@Override
public String call() throws Exception {
Thread.sleep(2000);
return null;
}
@Override
public void handle(TestEvent event) {
System.out.println("this is event " +event.getName());
done();
}
@Override
public Class<TestEvent> handleType() {
return TestEvent.class;
}
}
主方法:
OrangeAsyncEventLoop loop = new OrangeAsyncEventLoop();
OrangeTimeOutTask task = new OrangeTimeOutTask();
loop.registHandler(task);
loop.start();
new Thread(()->{
task.start();
}).start();
new Thread(()->{
loop.publishEvent(new TestEvent("allend is online"));
}).start();
通过结果可以看到是成功的,超时后会调用onTimeout方法,可以做个改进,就是如果done == true,则可以不继续执行call方法,比如这里的消息接收,如果一定时间内没有收到消息,就不再处理,不过没有什么关系
版权声明:本文为dw147258dw原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。