关于超时的实现---利用Timer

对于一些业务逻辑。需要用到超时处理的,在规定时间内没有得到回复,那么就需要处理。

比如:转账服务,

1)A转100给B。

2)B收到100后,回复A说,已经收到了。(这里就有时间限制)

3)A收到B的回复

对于操作1)是否有效需要操作3)来确定。操作1)是一个单独的请求。这个请求完了就完了。

核心是Timer的使用。验证超时就需要一个定时器。

超时处理需要一个hander

public abstract class TimeoutHandler {
    /** 执行周期(毫秒) */
    private int period = 1000 * 60 * 3;
    /** 延迟时间(毫秒) */
    private int delay = 1000 * 60 * 3;
    /** 执行次数(>=1) */
    private int times = 1;
    /** 定时器 */
    private Timer timer;

    /**
     * 超时处理
     *
     * @param _period
     *            执行周期(秒)
     * @param _times
     *            执行次数(>=1)
     */
    public TimeoutHandler(int _period, int _times) {
        super();
        this.period = 1000 * _period;
        this.delay = this.period;
        this.times = _times;

        timer = new Timer();
        if (times > 1) {// 执行多次
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (times > 1) {
                        times--;

                        retry();
                    } else {
                        end();

                        timer.cancel();// 结束任务
                    }
                }
            }, delay, period);
        } else {// 执行一次
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    end();

                    timer.cancel();// 结束任务
                }
            }, delay);
        }
    }

    /**
     * 终止任务
     */
    public void cancel() {
        if (timer != null) {
            timer.cancel();
        }
    }

    /**
     * 重试
     */
    public abstract void retry();

    /**
     * 终结
     */
    public abstract void end();

}

TimeOut

超时类的实际处理

public class Up0x26 extends TimeoutHandler {
    private static Logger logger = LoggerFactory.getLogger(Up0x26.class);
    /** 执行周期(秒) */
    private static final int period = 60 * 3;
    /** 执行次数(>=1) */
    private static final int times = 1;
    /** A */
    private String A;

    /**
     * 0x78超时处理
     *
     * @param params
     *            参数
     */
    public Up0x26(String A ) {
        super(period, times);

        this.A=A;
    }

    @Override
    public void retry() {
        logger.info("未及时收到回复 A:" + A );
    }

    @Override
    public void end() {
        logger.info("[超时]未及时A:停止失败.A" + A );
    }

针对多个超时需要一个管理器管理起来。

public class TimeoutManager {
    private static Logger logger = LoggerFactory.getLogger(TimeoutManager.class);
    /** 单例 */
    private static volatile TimeoutManager singleton = null;

    /** 缓存 -0x26 */
    private Map<String, List<TimeoutHandler>> Cache0x26 = null;

    /** 集合 - 超时处理类 */
    @SuppressWarnings("rawtypes")
    private static Class[] handlerSet = { Up0x26.class };

    /** 私有构造方法 */
    private TimeoutManager() {
        super();

        Cache0x26 = new ConcurrentHashMap<String, List<TimeoutHandler>>();
    }

    /** 获取实例 */
    public static TimeoutManager getInstance() {
        if (singleton == null) {
            synchronized (TimeoutManager.class) {
                if (singleton == null) {
                    singleton = new TimeoutManager();
                }
            }
        }
        return singleton;
    }

    /**
     * 获取缓存
     *
     * @param c
     *            超时处理对象类型
     * @return null 或 缓存对象
     */
    private Map<String, List<TimeoutHandler>> getCache(Class<? extends TimeoutHandler> c) {

         if (c == Up0x26.class) {
            return Cache0x26;
        } else {
            return null;
        }
    }

    /**
     * 添加超时监控
     *
     * @param key
     *            标识
     * @param handler
     *            超时处理对象
     */
    public void add(String key, TimeoutHandler handler) {
        if (key == null || "".equals(key = key.trim()) || handler == null) {
            return;
        }

        Map<String, List<TimeoutHandler>> cache = getCache(handler.getClass());
        if (cache == null) {
            logger.error("[添加超时监控]未知的对象类型:" + handler.getClass());
            return;
        }

        logger.info("[添加超时监控]key:" + key + " type:" + handler.getClass().getSimpleName());
        synchronized (cache) {
            List<TimeoutHandler> list = cache.get(key);
            if (list == null) {
                list = new ArrayList<TimeoutHandler>();
            }
            list.add(handler);

            cache.put(key, list);
        }
    }

    /**
     * 删除超时监控
     *
     * @param key
     *
     * @param c
     *            超时处理对象类型
     */
    public void delete(String key, Class<? extends TimeoutHandler> c) {
        if (key == null || "".equals(key = key.trim()) || c == null) {
            return;
        }

        Map<String, List<TimeoutHandler>> cache = getCache(c);
        if (cache == null) {
            logger.error("[删除超时监控]未知的对象类型:" + c);
            return;
        }

        logger.info("[删除超时监控]key:" + key + " type:" + c.getSimpleName());
        synchronized (cache) {
            List<TimeoutHandler> list = cache.get(key);
            if (list != null && !list.isEmpty()) {
                for (TimeoutHandler handler : list) {
                    handler.cancel();
                }
            }
            cache.remove(key);
        }
    }

    /**
     * 删除所有种类的超时监控
     *
     * @param key
     *            标识
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void deleteAll(String key) {
        if (key == null || "".equals(key = key.trim())) {
            return;
        }

        for (Class c : handlerSet) {
            delete(key, c);
        }
    }

    /**
     * 是否存在超时监控
     *
     * @param key
     *            标识
     * @param c
     *            超时处理对象类型
     * @return true:存在 false:不存在
     */
    public boolean containsKey(String key, Class<? extends TimeoutHandler> c) {
        if (key == null || "".equals(key = key.trim()) || c == null) {
            return false;
        }

        Map<String, List<TimeoutHandler>> cache = getCache(c);
        if (cache == null) {
            logger.error("[是否存在超时监控]未知的对象类型:" + c);
            return false;
        }

        return cache.containsKey(key);
    }

}

timeOutManager

超时的使用:

添加超时监控:

TimeoutManager.getInstance().add(key, new Up0x26(A));// 添加超时监控

删除超时监控:

TimeoutManager.getInstance().delete(key, Up0x26.class);// 删除超时监控
时间: 2024-08-29 14:35:43

关于超时的实现---利用Timer的相关文章

【Java】利用Timer与TimerTask定时执行任务

在Java里面定时执行一条任务多用于线程与进程配合Thread.currentThread().sleep(XXX);来实现,但是一些小型的任务其实完全利用Timer与TimerTask定时执行,Timer与TimerTask组合跟Thread与Runnable的区别在于,Timer与TimerTask是纯粹的单线程定时执行任务的计时器,相当于Thread与Runnable配合Thread.currentThread().sleep(XXX);的特殊情况,但程序写法定时器没有线程那么复杂.Thr

egret 示例实战六:利用Timer定时器,实现钟表秒针行走效果

1.建立一个圆和一根指针形状 1 let circle = new egret.Shape(); 2 circle.graphics.lineStyle(5,0x000000,1,true); 3 circle.graphics.drawCircle(0,0,170); 4 circle.graphics.endFill(); 5 circle.x = Main.instance.stage.stageWidth/2; 6 circle.y = Main.instance.stage.stage

利用Microsoft.Exchange.WebServices处理Office365邮件的几个属性

使用Microsoft.Exchange.WebServices可以很方便操作Office365邮件.这里列出几个重要的属性. 通常,代码里会先定义一个WebServices对象 ExchangeService service = new ExchangeService(); (1)service.Timeout = 200000; 默认service操作Office365是100秒,但是,如果程序连接服务器需要较长时间,会经常出现连接服务器超时现象,利用Timeout属性,可以延长请求的时间.

利用多线程解决多事务不同定时区间歇触发问题的一种方法

1.背景 项目中需要解决一个这样的问题:有两个事务均需要每隔几秒触发一次,但是两个事务都只是在规定的时间区域内才进行该行为.比如,在早上八点到晚上六点为上班时间,在这个时间段内两个事务必须每隔几秒被执行一次,下班后则停止工作. 2.思路 这个问题最开始我是想利用timer来解决,即做两个timer,一个timer来控制一个事务,然后在各事务对应时间区域内执行. 但是考虑到Timer是在主线程里执行的,Thread 是在自己的线程中执行的,在多核多线程的 CPU 中,利用Thread的效率高更高一

JDK中的Timer和TimerTask详解

目录结构: Timer和TimerTask 一个Timer调度的例子 如何终止Timer线程 关于cancle方式终止线程 反复执行一个任务 schedule VS. scheduleAtFixedRate 一些注意点 1. Timer和TimerTask Timer是jdk中提供的一个定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次. TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务. 2.

Timer与ScheduledThreadPoolExecutor

在实际应用中,有时候我们需要创建一些个延迟的.并具有周期性的任务,比如,我们希望当我们的程序启动后每隔1小时就去做一次日志记录.在JDK中提供了两种方法去创建延迟周期性任务. Timer Timer是java.util包下的一个类,在JDK1.3的时候被引入,Timer只是充当了一个执行者的角色,真正的任务逻辑是通过一个叫做TimerTask的抽象类完成的,TimerTask也是java.util包下面的类,它是一个实现了Runnable接口的抽象类,包含一个抽象方法run( )方法,需要我们自

Qt之处理QNetworkAccessManager网络连接超时

简述 在网络操作中,经常会由于各种原因引起网络连接超时,究竟何为网络连接超时? 网络连接超时:在程序默认的等待时间内没有得到服务器的响应 简述 超时原因 Qt 中的网络连接超时 超时原因 引起网络连接超时的原因很多,下面,列举一些常见的原因: 网络断开,不过经常显示无法连接 网络阻塞,导致你不能在程序默认等待时间内得到回复数据包 网络不稳定,网络无法完整传送服务器信息 系统问题,系统资源过低,无法为程序提供足够的资源处理服务器信息 设备不稳定,如网线松动.接口没插好等等 网络注册时系统繁忙,无法

利用webbrowser自动查取地点坐标

概述 有时候我们需要去查询某些地点的坐标,那么我们可以用百度提供的坐标拾取系统http://api.map.baidu.com/lbsapi/getpoint/index.html,但是会发现它只能一个一个的查,还要不停的点击,要是查询的量特别大,比如说要查某个省的所有村,甚至全国所有村的坐标怎么办,人工查寻绝对会累趴下.所以我就写了一个这样的工具:自动查取地点坐标工具 功能 现在这个工具主要是针对的村和镇,因为查询市,县范围比较大,百度的坐标拾取系统也经常拾取不到坐标. 1.数据框要求输入是j

【Listener】利用监听器Listener以MVC的思想通过JSP+Servlet+JDBC完成在线用户列表的输出

Servlet,监听器Listener与<[Filter]拦截器Filter>(点击打开链接)是JSP的三大核心组件,实际上监听器Listener相当于数据库里面的触发器,一旦用户触发了某种行为,则可以通过相关的Java文件执行相应的程序.用户在浏览网页的过程中,主要有打开浏览器的动作,对应的行为是Session的创建,可是,用户关闭浏览器的动作,并不是对应Session的消失,因此对于Session的消失我们意义不大:访问任意网页的动作,对应的行为是request请求的创建,request的