java实现超时任务

有时候碰到一种情况,远程请求一个任务,但是请求时间不能超过一定时间,超过后按超时处理,这种情况我们可以用一段代码来实现,但是如果我们实现成一个类 ,则可以让代码更简洁,更具有健壮性

首先定义一个接口

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版权协议,转载请附上原文出处链接和本声明。