关于超时的实现---利用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);// 删除超时监控

 

posted @ 2017-09-16 14:30  钟政123  阅读(643)  评论(0编辑  收藏  举报