关于超时的实现---利用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(); }
超时类的实际处理
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.getInstance().add(key, new Up0x26(A));// 添加超时监控
删除超时监控:
TimeoutManager.getInstance().delete(key, Up0x26.class);// 删除超时监控
学习的时间不一定要特定安排