最近为公司框架提供了基于ID的单例的任务调度基类,用于集群的环境下,一个任务同一时间只能被调度一次。
接口声明
继承该基类的任务需要覆盖两个抽象函数:
protected abstract String getServiceID();//服务ID,与数据库中的和timeservice.xml中的要配置相同
protected abstract void doTask();//执行任务,需覆盖的业务方法
实现机理
每个任务要有唯一的ServiceId,该任务在t_s_sys_timeservice 中有一条记录,同时有一个state记录着状态信息,state为0表示未占用,state为1表示已占用。
设计上还要考虑处理异常的情况,通过引入一个超时时间,如果已经超时,则认为改状态为未被占用
关键代码
package com.itown.framework.schedule; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.log4j.Logger; import com.itown.framework.exception.ServiceInvokeException; import com.itown.framework.impl.ThreadContext; import com.itown.framework.persistence.DataSourceFactory; import com.itown.framework.persistence.ParamsMaker; import com.itown.framework.persistence.SingleDBHelper; import com.itown.framework.transaction.FrameworkTransaction; import com.itown.framework.transaction.JDBCTransaction; /** * timeout_interval用来设定超时时间,单位是秒,极端情况state可能为1,当达到超时时间时,再次执行,要求超时时间一定要大于task的执行时间 */ public abstract class SingletonTimeService extends TimeService { private static final Logger logger = Logger.getLogger(SingletonTimeService.class); private String selectSql = "select * from t_s_sys_timeservice where (id = ? and state = '0') or (id = ? and sysdate > update_date + timeout_interval/86400 )"; private String updateLockSql = "update t_s_sys_timeservice set update_date = sysdate,state = 1 where (id = ? and state = '0') or (id = ? and sysdate > update_date + timeout_interval/86400 )"; private String updateUnlockSql = "update t_s_sys_timeservice set update_date = sysdate,state = '1' where id = ?"; public void doTimeService() { String funcName = "SingletonTimeService.doTimeService"; logger.info(funcName + " begin time:" + System.currentTimeMillis()); ThreadContext ctx = ThreadContext.getThreadContext(); FrameworkTransaction _tr = null; Connection _conn = null; try { _conn = DataSourceFactory.getDefaultConnection(); _tr = new JDBCTransaction(_conn); _tr.begin(); //争任务,此处无法采用框架提供的封装 PreparedStatement ps = null; ResultSet rs = null; try { logger.info(funcName + " selectSql:" + selectSql); logger.info(funcName + " id:" + getServiceID()); ps = _conn.prepareStatement(selectSql); ps.setString(1, getServiceID()); ps.setString(2, getServiceID()); rs = ps.executeQuery(); } catch (SQLException ex) { logger.error(ex); throw ex; } int result =0;//result > 0 表示抢到任务 if(rs.next()){ SingleDBHelper helper = new SingleDBHelper(_conn); //锁定任务 try{ logger.info(funcName + " updateLockSql:" + updateLockSql); logger.info(funcName + " id:" + getServiceID()); result=helper.executeUpdate(updateLockSql,ParamsMaker.makeParams(getServiceID())); _tr.commit(); }catch(Exception e){ logger.error(e); } //执行任务 try{ _tr.begin(); logger.info(funcName + " 开始执行timeservice(id="+getServiceID()+")任务..."); if(result>0){ doTask(); } logger.info(funcName + " 结束执行timeservice(id="+getServiceID()+")任务。"); }catch(Throwable e){ logger.error(e); throw e; } //解锁 //注释此timeservice解锁业务,超时会自动满足timeservice执行条件; try{ logger.info(funcName + " updateUnlockSql:" + updateUnlockSql); logger.info(funcName + " id:" + getServiceID()); if(result>0){ helper.executeUpdate(updateUnlockSql,ParamsMaker.makeParams(getServiceID())); } }catch(Exception e){ logger.error(e); } } //事务相关操作 _tr.commit(); } catch (Throwable ex) { if (_tr != null) { try { _tr.rollback(); } catch (Exception ex1) { logger.error(ex1); } } throw new ServiceInvokeException("调度异常", ex); } finally { ctx.runShieldStatements(); DataSourceFactory.release(_conn); } } protected abstract String getServiceID(); protected abstract void doTask(); }
相关推荐
综上所述,"Unity3D通用单例基类"是一个强大的工具,它可以适应多种情况下的单例需求,无论是非脚本组件还是Mono脚本,甚至Prefab加载。通过这个基类,开发者可以更方便地管理共享资源,确保网络连接的一致性和效率...
Unity游戏开发中常用的三种单例模式基类框架,包含三个文件,分别是不继承mono的,继承mono但需要手动挂载的,继承mono可自动挂载的,前两种的使用会更加广泛
在多线程环境下,C#经典单例可能存在问题。为了确保在任何时刻只有一个线程能执行创建单例的代码,可以使用锁(lock)来同步。但是,Unity主要在主线程运行,因此在大部分情况下并不需要特别处理线程安全性。不过,...
- 在分布式环境下,如集群环境,单节点的定时任务可能无法满足需求,这时可以考虑使用分布式定时任务解决方案,如XXL-JOB、Elastic-Job等。 - 这些框架提供中心化的任务调度服务,可以实现任务的分布式部署和执行...
单例模式是软件设计模式中的一种,它的主要目的是确保一个类只有一个实例,并提供全局访问点。在C#中实现单例模式,可以有效地控制资源的使用,限制类的实例化次数,尤其适用于需要频繁实例化然后销毁的对象或者创建...
### VC环境下可重用基类的开发及其应用 #### 引言 软件开发中的面向对象方法自20世纪80年代末提出以来,在近几十年内得到了广泛应用。面向对象技术之所以能够逐渐取代传统的软件开发方法,一个重要原因是其支持...
1. **定义类**:首先,创建一个类,例如`SingletonClass`,它继承自你想要单例化的基类,例如`QObject`。`QObject`类使得我们可以利用其强大的信号和槽机制。 ```cpp class SingletonClass : public QObject { Q_...
任务调度器通常用于决定何时、何地以及如何执行特定的任务,尤其是在资源有限或需要优化性能的环境中。 "scheduler:基于轻量级 C++ boost 的任务调度器类"这个标题表明,我们讨论的是一个使用Boost库实现的轻量级...
虚基类的主要作用是确保即使在多继承的情况下,基类也只被继承一次。这通常通过编译器为每个包含虚基类的派生类添加一个指向基类对象的指针来实现。这样可以确保每个派生类只访问到唯一的基类实例。 #### 三、案例...
6. **字符串加密**:在C#中,可以使用System.Security.Cryptography命名空间下的类进行字符串加密。例如,AES(高级加密标准)、RSA(公钥加密算法)和SHA(安全散列算法)等,这些加密算法可用于保护敏感信息的安全...
C++多线程是编程中一个重要的概念,它允许程序同时执行多个独立的任务,从而提高程序的执行效率。在C++中,多线程的实现通常依赖于平台相关的API,如POSIX线程库(pthread)对于Unix-like系统。本文将深入探讨C++中...
本文实例讲述了PHP基于单例模式实现的数据库操作基类。分享给大家供大家参考,具体如下: 配置文件: <?php $db = array( 'host'=>'localhost', 'user'=>'root', 'password'=>'', 'database'=>'test', ) ?&...
总结来说,这个“Linux C/C++线程基类”源代码项目提供了一个便捷的线程管理框架,使得在Linux环境下使用C++进行多线程编程变得更加简单和直观。通过理解和利用这个基类,开发者可以专注于业务逻辑,而无需关心底层...
7. **System.Threading.Thread** 和 **System.Threading.Tasks.Task**:线程和任务是多线程编程的核心。Thread类代表执行代码的独立线程,而Task类是异步编程的主要机制,用于执行异步操作。 8. **System.Net....
在C#编程中,基类和工具类是两个重要的概念,它们在软件开发过程中起着不可或缺的作用。基类,也称为父类或超类,是用来创建其他类的基础,它定义了共享属性和行为,子类可以继承这些特性,从而实现代码的重用和扩展...
《.Net 基类积累:深入理解和应用》 在.NET框架中,基类是所有对象的起点,它们提供了一组通用的功能,为其他类提供了基础。Asp.Net中的基类尤其重要,因为它们构成了Web应用程序的核心结构。本文将深入探讨一些...
c# xml 操作 基类
在高并发环境下,这种优化尤为重要,因为它避免了频繁的数据库连接创建和销毁,减少了系统资源的消耗。 这个基类通常会支持多种数据库,如SQL Server、Oracle和OLE DB,这些是常见的企业级数据库系统。SQL Server是...